弹幕词云生成器

弹幕词云生成器

这是一个python爬虫的初学练手项目,作用是从 bilibili.com 爬取弹幕并生成词云。

爬取弹幕

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def get_cid(bvid):
"""获取视频cid"""
url = 'https://api.bilibili.com/x/web-interface/view?bvid={}'.format(bvid)
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 Edge/16.16299',
'Referer': 'https://www.bilibili.com/video/{}'.format(bvid)
}
response = requests.get(url, headers=headers)
data = response.json()
cid = data['data']['cid']

return cid

"""
# 将Python对象转化为JSON格式的字符串,并输出
print(json.dumps(data, indent=4, ensure_ascii=False))
print(cid)
"""

传入视频的BV号,在headers里面定义了一个请求头,用于描述发起请求的客户端信息。在这段代码中,我们手动设置了一个浏览器用户代理,用于模拟浏览器的行为。

然后把获取到的响应转换成json格式,从响应里提取出视频的cid值。

这篇文章,详细解析了获取到的json:从bilibili获取到的json解析。可以看到一个视频里,不同分p有不同的cid

问我为什么不写不同分p的情况?因为我懒,有需要再写(2023.4.14日备注,此问题已修复)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
def get_danmu(cid):
"""获取弹幕"""
url = 'https://comment.bilibili.com/{}.xml'.format(cid)
response = requests.get(url)
xml_content = response.content.decode('utf-8')
root = ET.fromstring(xml_content)
danmu_list = []
for d in root.iter('d'):
danmu = d.text
p_attrs = d.attrib['p']
p_attrs_list = p_attrs.split(',')
danmu_dict = {
'text': danmu,
'time': float(p_attrs_list[0]),
'mode': int(p_attrs_list[1]),
'fontsize': int(p_attrs_list[2]),
'color': int(p_attrs_list[3]),
'timestamp': int(p_attrs_list[4]),
'pool': int(p_attrs_list[5]),
'userid': p_attrs_list[6],
'rowid': int(p_attrs_list[7]),
'duration': int(p_attrs_list[8]),
}
danmu_list.append(danmu_dict)
return danmu_list

传入cid,b站的弹幕都存在https://comment.bilibili.com/{cid}.xml里,这个地址可以用浏览器直接访问。用爬虫访问这个URL,获取弹幕列表。

生成词云

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
def word_cloud_generator(json_name):
# 读取json文件
with open(json_name, 'r', encoding='utf-8') as f:
data = json.load(f)

# 获取所有弹幕内容
text = ''
for item in data:
text += item['text']

# 加载停用词表
stopwords = set()
with open('cn_stopwords.txt', 'r', encoding='utf-8') as f:
for line in f:
stopwords.add(line.strip())

# 使用jieba进行分词,去掉停用词
words = [word for word in jieba.cut(text) if word not in stopwords]

# 将分词结果转换为字符串
words_str = ' '.join(words)

# 生成词云
wc = WordCloud(background_color='white', width=1000, height=800, font_path='msyh.ttc')
wc.generate(words_str)

"""
# 显示词云
plt.imshow(wc)
plt.axis('off')
plt.show()
"""

# 保存词云
filename = os.path.splitext(json_name)[0] + '.png'
wc.to_file(filename)

把获取的弹幕进行分词,这里使用了jieba中文分词,把句子分成词语。然后加载停用词表,去掉诸如这个、那个、是、吧等类似无意义的词语。设置词云图片的背景颜色,图片大小,生成词云图片。