一、基本介绍
B站近些年正顺应着网络新媒体的潮流,凭借其创作激励计划吸引着越来越多的人加入它的平台并产生了大量的作品。可是作为一个up主,如何选取适合的主题进行创作,是否可以通过对网站的某些数据进行爬取分析,从而获取在某一个特定的时间段,什么内容最受用户的喜欢?根据这个初衷,我观察了B站的网站内容,发现其自身包含着一个排行榜,所以我想我是否可以通过爬取排行榜的视频链接并获取所有视频的点赞数据等,将这些数据当作权值赋予视频的标签,并将其可视化出来,不过由于我刚学习爬虫与python不久,代码可能还有些不足之处,不过基本可以实现初步设想。
二、使用的工具
语言环境:python3.7版本
第三方库: selenium(由于b站使用的是动态渲染的网址,使用selenium可以爬取到动态渲染的信息),BeautifulSoup,pytagcloud,pygame
三、前期准备
selenium:这里我使用了selenium.webdriver的Chrome,所以需要安装电脑里下载的Chrome对应版本的ChromeDriver,可以通过镜像网获取。
详情可以通过:https://www.cnblogs.com/lfri/p/10542797.html 了解,我觉得这位讲的很详细了。
BeautifulSoup:可以直接通过pip 获取 :pip3 install beautifulsoup4
pytagcloud:获取:pip3 install pytagcloud
不过在使用的时候需要确保有安装pygame,因为pytagcloud有import 该库。传入其make_tags()函数的第一个参数应该是dict_items类的对象,可以通过字典的items()(python3)获取该对象。
pytagcloud中文字体设置:
1.打开pytagcloud文件夹中的fonts文件夹,将对应字体的ttf文件移入。
2.打开fonts中的fonts.json文件,将加入的字体写进文件中,注意json文件的格式
函数传入的fontname就为对应的“name”,如果没有中文文件将无法生成中文词云!
四、代码实现
(一)爬取B站排行榜
from selenium import webdriver
from bs4 import BeautifulSoup
import time
class LinkCatch:
'返回视频网址列表'
_url = ''
_brower = webdriver.Chrome()
_html=''
_arrLink =[]
def __init__(self, url:str):
self._url=url#设置排行榜的url
def __catch(self):
print('LinkCatch.catch()正在运行。。。')
self._brower.get(self._url)
time.sleep(3)#等待,防止爬取到未加载完毕的网址
self._html=self._brower.page_source
def __dataAnalyze(self):
print('LinkCatch.dataAnalyze()正在运行。。。')
soup = BeautifulSoup(self._html,'lxml')
temparr = soup.find_all(class_='rank-item')
for item in temparr:
self._arrLink.append(item.a['href'])#储存网址
def run(self):
#获取并返回网址列表
self.__catch()
self.__dataAnalyze()
#self._brower.close()
return self._arrLink
(二)获取视频链接的点赞数等数值信息与标签
class DataCatch:
'返回一个字典数组,包含标签与硬币点赞数的总数(权值化)'
_linkArr=[]
_likeRate = 1
_coinRate = 1
_shareRate = 1
_collectRate = 1
_brower = webdriver.Chrome()
__keyword = ['share','collect','coin','like']
__timeout = 3 #设置睡眠等待时间,可以使得未获取的视频数据变少
__defaultList=[]
def __init__(self, linkArr,rate:int=1000):
#传入网址列表
self._linkArr = linkArr
def setRate(self,share:float,collect:float,coin:float,like:float):
#设置不同数值的权占比
print('DataCatch.setRate()正在运行。。。')
self. _likeRate =like
self._coinRate=coin
self._shareRate =share
self._collectRate =collect
def __dataDeal(self,arr):
#返回不同数值权占比乘以其数值之和 初始化为1:1:1:1
print('DataCatch.dataDeal()正在运行。。。')
temparr =[]
for item in arr:#处理字符串含有的‘万’
temp =0
if not item.isdigit():
temp += float(item.split('万')[0])
temp*=10000
else:
temp=float(item)
temparr.append(temp)
total = 0
total = temparr[0]* self._shareRate+temparr[1]*self._collectRate+temparr[2]*self._coinRate+temparr[3]*self. _likeRate
return total
def __synthesis(self,tagArr,numberArr):
#传入标签数组和硬币等数量数组,返回一个标签与权值字典,即将一个视频的标签和其权值合成
print('DataCatch.synthesis()正在运行。。。')
N=self.__dataDeal(numberArr)
dic ={
}
for item in tagArr:
dic.update({
item:N})
return dic
def __catchdata(self):
#获取所需视频网址的所有信息
print('DataCatch.catchdata()正在运行。。。')
dic= {
}
for item in self._linkArr:
tagArr = []
numberArr=[]
self._brower.get(item)
time.sleep(self.__timeout)
for name in self.__keyword:
numberArr.append(self._brower.find_element_by_class_name(name).text)
if not numberArr[0].split('万')[0].split('.')[0].isdigit() :
#判别是否抓取到未渲染完成的网址,是的话将其放入defualtlist,这里未对未渲染完成的网址进行重新获取
print("Link"+item+"doesn't got!")
self.__defaultList.append(item)
continue
soup =BeautifulSoup(self._brower.page_source,'lxml')
for item in soup.find_all(name='li',class_='tag'):
tagArr.append(item.a.text)
tempdic = self.__synthesis(tagArr,numberArr)
keyArr = tempdic.keys()
for item in keyArr:
#如果标签已经存在在字典里,将其权值与字典里的权值相加,得到新的权值,如果没有,将标签与其权值放进字典
if item in dic:
dic.update({
item:dic.get(item)+tempdic.get(item)})
else:
dic.update({
item:tempdic.get(item)})
return dic
def printDefaultList(self):
i=1
for item in self.__defaultList:
print(i + item)
i=i+1
def getDefaultList(self):
#用于重新获取,不过懒得写重新获取了,dbq
return self.__defaultList
def run(self):
#返回标签及其权值的字典,以供可视化使用
print('DataCatch.run()正在运行。。。')
self.printDefaultList()
return self.__catchdata()
(三)进行可视化
if __name__ =='__main__':
from pytagcloud import create_tag_image, make_tags
from pytagcloud.lang.counter import get_tag_counts
url='https://www.bilibili.com/ranking?spm_id_from=333.851.b_7072696d61727950616765546162.3'#B站排行榜的URL
linkArr = LinkCatch(url).run()
dic = DataCatch(linkArr).run()
count = dic.items()
tags = make_tags(count, maxsize=120)#maxsize设置字体的最大大小
create_tag_image(tags, 'D://TEST//B站爬虫测试.png', size=(1000,1000), fontname='Deng')#这里的Deng为等线字体,需要自己添加进pytagcloud的字体库中
(四)获取的成品