python爬取bilibili弹幕_爬取Bilibili弹幕并制作词云图

最近发现词云图挺有意思的,正好在家闲来无事,就尝试做了一下B站视频弹幕的词云,顺便重拾一下爬虫技能。

寻找请求

首先用Chrome随便打开一个视频开始抓包,猜测弹幕信息是通过Ajax请求得到的,选中XHR,很轻松就可以找到弹幕请求的url。

https://api.bilibili.com/x/v1/dm/list.so?oid=152796906

打开之后发现是一个XML格式的文件,弹幕信息包含在d标签的text里。d标签p属性中的信息猜测可能是弹幕出现的时间、弹幕类型、弹幕发送时间戳、经加密的用户信息、弹幕在数据库里的ID等

但仔细观察发现这个XML里只有500条弹幕信息,这500条弹幕正是用户最新发布的500条弹幕,也就是视频旁边弹幕下拉框列表里最新的500条弹幕这里多出的49条弹幕是在我打开网页到截图这段时间里多出的弹幕,但在XML里仍只有500条

之后我尝试查看历史弹幕,找到历史弹幕的请求url(以2020-02-19的弹幕为例)

https://api.bilibili.com/x/v2/dm/history?type=1&oid=152796906&date=2020-02-19

可以看到这两个url差异很大,打开之后发现XML里仍然只有500条弹幕信息,最重要的是这些历史弹幕的获取需要用户登录,如果未登录返回的结果是这个样子

{"code":-101,"message":"账号未登录","ttl":1}

也就是说要请求历史弹幕需要带上cookie………那还是算了吧,就先拿500条弹幕玩一玩。

请求的url里只有一个参数oid,这个参数应该可以在主页面里找到(值得注意的是这个oid值在主页面的response里的标签为cid,真的坑……)

找到oid值之后我们的任务基本上已经完成了50%,接下来我们就可以写代码了。

python获取视频弹幕信息

1、请求视频页面

AV是av号,PAGE是视频集数,默认为1,headers里除了UA随便加了几个

def get_html():

url = "https://www.bilibili.com/video/av%s?%s" % (AV, PAGE)

headers = {

"Sec-Fetch-Dest": "document",

"Sec-Fetch-Mode": "navigate",

"Host": "www.bilibili.com",

"Referer": "https://search.bilibili.com",

"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.87 Safari/537.36",

}

response = requests.get(url=url, headers=headers)

try:

if response.status_code == 200:

return response.text

else:

print('请求页面出错', response.url)

except RequestException:

print('请求页面出错', response.url)

return None

2、获取oid/cid

用正则得到oid/cid,顺便获取一下视频的发布时间和标题

def get_info(html):

pattern = re.compile(r'"cid":(\d+),"page":%s' % PAGE)

pattern1 = re.compile(r'"title":"(.*?)","pubdate":(\d+)')

cid = re.search(pattern, html).group(1)

title, pubdate_u = re.search(pattern1, html).groups()

pubdate = time.strftime("%Y-%m-%d%H:%M:%S", time.localtime(int(pubdate_u))) # 时间戳转str

return cid, title, pubdate

3、获取弹幕信息

这里为了方便就用了Xpath,顺便提取了第一条弹幕的发送时间

def get_dm(cid):

url = 'https://api.bilibili.com/x/v1/dm/list.so?oid=%s' % cid

headers = {

"Sec-Fetch-Dest": "empty",

"Sec-Fetch-Mode": "cors",

"Sec-Fetch-Site": "same-site",

"Host": "api.bilibili.com",

"Origin": "https://www.bilibili.com",

"Referer": "https://www.bilibili.com/video/av%s" % AV,

"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.87 Safari/537.36",

}

response = requests.get(url=url, headers=headers)

try:

if response.status_code == 200:

html = etree.HTML(response.content)

dm = html.xpath('//d/text()')

s_utime = html.xpath('//d[1]/@p')[0].split(',')[4] # 第一条弹幕的发送时间

s_time = time.strftime("%Y-%m-%d%H:%M:%S", time.localtime(int(s_utime)))

return dm, s_time

else:

print('获取弹幕出错', response.url)

except RequestException:

print('获取弹幕出错', response.url)

return None

4、词云图制作

使用jieba分词和wordcloud

def ciyun(dm):

result = jieba.analyse.extract_tags(dm, withWeight=True)

wc = wordcloud.WordCloud(

font_path=r'C:/Windows/Fonts/simhei.ttf',

# background_color='White',

width=720, height=480,

max_font_size=150,

)

wc.generate_from_frequencies(dict(result))

wc.to_file('cy.png')

5、mian函数

def main():

html =get_html()

if html:

cid, title, pubdate = get_info(html)

if cid:

dm, s_time = get_dm(cid)

if dm:

print('*' * 50)

print('视频名称:%s,发布日期%s' % (title, pubdate))

print('从%s起,共获取到%d条弹幕' % (s_time, len(dm)))

dm = ''.join(dm) # 把所有弹幕连在一起

ciyun(dm)

if __name__ == '__main__':

main()

6、运行结果

Building prefix dict from the default dictionary ...

Loading model from cache C:\Users\pty666\AppData\Local\Temp\jieba.cache

**************************************************

视频名称:【 钉 钉 本 钉 ,在 线 求 饶 】,发布日期2020-02-16 20:24:22

从2020-02-21 13:51:45起,共获取到500条弹幕

Loading model cost 0.913 seconds.

Prefix dict has been built successfully.

Process finished with exit code 0矩形的词云图确实有点丑……

其他视频词云图

在我看了其他视频后发现,其实不同视频的弹幕存储量是不同的,有的是500,有的是1000,有的甚至可以达到6000、8000,形式也有所不同。以8000为例,这些弹幕并不是一天的,而是从选中日期开始向前数8000条弹幕。

最后放两个视频的词云图,猜一猜是哪两个视频 (狗头) 。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值