手把手教你获取弹幕数据
1. 简单说明
没看过直播的朋友不要紧,有回放呀!整个视频已经为大家整理好了,从开幕式,到五场比赛,再到夺冠时刻,一共7个视频。
每个视频中,都有粉丝发布的弹幕。今天要做的,就是获取每个视频里面的弹幕数据,看看粉丝在躁动的心情下,说了点啥?
不得不说,B站网页的变化速度真快,我记得去年还是很容易找到的。但是今天却一直没有找到。
但是没有关系,我们直接将以前的弹幕数据网址接口拿过来使用就行。
API: https://api.bilibili.com/x/v1/dm/list.so?oid=XXX
这个oid其实就是一串数字,每个视频都有一个独特的oid。
2. oid数据找寻
本小节就带着大家一步步找寻这个oid。要找到oid,首先要找到一个叫做cid的东西。
点击F12,先打开开发者工具,按照图中提示,完成1-5处的操作。
第3处:这个页面有很多个请求,但是你需要找到这个以pagelist开头的请求。
第4处:观察对应的Header下方,有一个Request URL,我们要的cid就在这个网址中。
第5处:观察对应的Preview下方,就是请求Request URL,响应给我们的结果,图中圈起来的就是我们要的cid数据。
2. cid数据获取
上述我们已经找到了Request URL,下面我们只需要发起请求,获取里面的cid数据即可。
import requests import json url = 'https://api.bilibili.com/x/player/pagelist?bvid=BV1EP4y1j7kV&jsonp=jsonp' res = requests.get(url).text json_dict = json.loads(res) #pprint(json_dict) for i in json_dict["data"]: oid = i["cid"] print(oid)
结果如下:
其实,这里cid对应的数字串,就是oid后面的数字串。
3. 拼接url
我们不仅有了弹幕api接口,也有了cid数据,接下来将它们进行拼接,就可以得到最终的url。
url = 'https://api.bilibili.com/x/player/pagelist?bvid=BV1EP4y1j7kV&jsonp=jsonp' res = requests.get(url).text json_dict = json.loads(res) #pprint(json_dict) for i in json_dict["data"]: oid = i["cid"] api = "https://api.bilibili.com/x/v1/dm/list.so?oid=" url = api + str(oid) print(url)
结果如下:
一共有7个网址,分别对应7个视频里面的弹幕数据。
随便点开一个查看:
4. 正则提取弹幕数据并保存
有了完整的url后,我们要做的就是提取里面的数据,这里还是直接采用正则表达式。我们以其中一个视频为例,为大家讲解。
final_url = "https://api.bilibili.com/x/v1/dm/list.so?oid=437729555" final_res = requests.get(final_url) final_res.encoding = chardet.detect(final_res.content)['encoding'] final_res = final_res.text pattern = re.compile('<d.*?>(.*?)</d>') data = pattern.findall(final_res) with open("弹幕.txt", mode="w", encoding="utf-8") as f: for i in data: f.write(i) f.write("\n")
结果如下:
这只是其中一页的数据,共有7200条数据。
完整代码
上述我已经分步为大家讲解了每一步过程,这里我直接将代码封装成函数。
import os import requests import json import re import chardet # 获取cid def get_cid(): url = 'https://api.bilibili.com/x/player/pagelist?bvid=BV1EP4y1j7kV&jsonp=jsonp' res = requests.get(url).text json_dict = json.loads(res) cid_list = [] for i in json_dict["data"]: cid_list.append(i["cid"]) return cid_list # 拼接url def concat_url(cid): api = "https://api.bilibili.com/x/v1/dm/list.so?oid=" url = api + str(cid) return url # 正则提取数据 def get_data(url): final_res = requests.get(url) final_res.encoding = chardet.detect(final_res.content)['encoding'] final_res = final_res.text pattern = re.compile('<d.*?>(.*?)</d>') data = pattern.findall(final_res) return data # 保存数据 def save_to_file(data): with open("弹幕数据.txt", mode="a", encoding="utf-8") as f: for i in data: f.write(i) f.write("\n") cid_list = get_cid() for cid in cid_list: url = concat_url(cid) data = get_data(url) save_to_file(data)
结果如下:
确实很棒,一共3.1w数据!
保姆级词云图制作教程
对于获取到了 数据,我们 利用EDG背景图,制作一个好看的词云图。
# 1 导入相关库 import pandas as pd import jieba from wordcloud import WordCloud import matplotlib.pyplot as plt from imageio import imread import warnings warnings.filterwarnings("ignore") # 注意:动态添加词语集 for i in ["EDG","永远的神","yyds","牛逼","发来贺电"] jieba.add_word(i) # 2 读取文本文件,并使用lcut()方法进行分词 with open("弹幕数据.txt",encoding="utf-8") as f: txt = f.read() txt = txt.split() txt = [i.upper() for i in txt] data_cut = [jieba.lcut(x) for x in txt] # 3 读取停用词 with open("stoplist.txt",encoding="utf-8") as f: stop = f.read() stop = stop.split() stop = [" "] + stop # 4 去掉停用词之后的最终词 s_data_cut = pd.Series(data_cut) all_words_after = s_data_cut.apply(lambda x:[i for i in x if i not in stop]) # 5 词频统计 all_words = [] for i in all_words_after: all_words.extend(i) word_count = pd.Series(all_words).value_counts() # 6 词云图的绘制 # 1)读取背景图片 back_picture = imread("EDG.jpg") # 2)设置词云参数 wc = WordCloud(font_path="simhei.ttf", background_color="white", max_words=1000, mask=back_picture, max_font_size=200, random_state=42 ) wc2 = wc.fit_words(word_count) # 3)绘制词云图 plt.figure(figsize=(16,8)) plt.imshow(wc2) plt.axis("off") plt.show() wc.to_file("ciyun.png")
结果如下: