翼度科技»论坛 编程开发 python 查看内容

【python爬虫+情感分析】B站黑神话悟空热门弹幕情感分析及词云生成

4

主题

4

帖子

12

积分

新手上路

Rank: 1

积分
12
黑神话悟空背景介绍

最近黑神话悟空这款游戏可谓红遍大江南北,不仅IGN给出了8分的高分,就连央视新闻都有报道。作为国内第一款单机大作:出圈的是游戏,输出的是中国文化,受到了广大游戏玩家的追捧和赞扬。
针对此热门事件,老王我用python爬虫和情感分析技术,针对B站的弹幕数据,分析了黑神话悟空这款热门游戏弹幕的舆论导向,并生成了词云图,下面我们来看一下,python代码是如何实现的。
B站弹幕接口分析

目标网址:
B站最新的弹幕接口采用的是 protobuf编码 的格式,我们来简单分析一下。
通过搜索黑神话悟空视频弹幕上的关键字,发现压根搜不到,那说明大概率是加了密或进行了特殊编码的文字。

这也难不倒我们,就当多干点苦力活吧,一个一个的从接口里找一下吧!
通过查找,我们找到了疑似弹幕的接口,看起来是一个二进制文件。

直接预览出现乱码,但是可以看见一部分的弹幕内容,已经可以确定这个就是弹幕文件了,但是有许多乱码在里面,不过仍可以查看部分弹幕内容。
老王这次不准备对protobuf编码的文字进行解码,而是告诉大家一个更简单的方法
通过多方分析,发现B站的弹幕还有2个不加密的接口:
1.http://comment.bilibili.com/{cid}.xml
2.https://api.bilibili.com/x/v1/dm/list.so?oid=
这两种返回的结果一致!但都不全,都是只有部分弹幕!但用来做此次分析足够了!
以B站视频 为例,我们打开这个黑神话悟空的网站,通过 查看网页源代码 ,可以找到对应的cid=1656402207,我们直接按照上面的格式替换一下,得到了对应的弹幕接口的网址是:http://comment.bilibili.com/1656402207.xml

从上面可以发现,这不就是我们要的弹幕数据吗?而且都不用解密了,真爽!下面直接开始撸代码!
弹幕爬取代码详解

首先,导入需要用到的python库
  1. import requests
  2. import re   # 正则表达式
  3. import json # json转换
  4. from lxml import etree  # xml解析
  5. import pandas as pd  # 存取csv
  6. import os
  7. import datetime
复制代码
然后,我们请求一下视频地址,并拿到视频信息
  1. resp = session.get(url)
  2. # 解析页面数据
  3. html_content = resp.text
  4. obj_str = re.search('window.__INITIAL_STATE__=(.*?);', html_content).group(1)
  5. obj = json.loads(obj_str)        # 解析出来的视频信息(转换为json格式)
复制代码
有很多信息我们是用不到的,这里我们只提取我们需要的数据
  1. # 获得所需的视频信息
  2. video_data = obj["videoData"]
  3. stat = video_data["stat"]
  4. return {
  5.     "aid": video_data["aid"],       # aid,pid
  6.     "cid": video_data["cid"],       # cid,oid
  7.     "bvid": video_data["bvid"],     # url链接上的视频id
  8.     "title": video_data["title"],   # 标题
  9.     "desc": video_data["desc"], # 描述
  10.     "pubdate": video_data["pubdate"],   # 发布日期 时间戳
  11.     "view": stat["view"],   # 观看数
  12.     "danmaku": stat["danmaku"],     # 弹幕数
  13.     "reply": stat["reply"], # 回复数
  14.     "favorite": stat["favorite"],   # 收藏数
  15.     "coin": stat["coin"],   # 投币数
  16.     "share": stat["share"],   # 分享数
  17.     "like": stat["like"],   # 点赞数
  18. }
复制代码
然后就是用上面我们拿到的cid,去请求那个xml接口地址
  1. url = f'https://comment.bilibili.com/{cid}.xml'
  2. # 发送请求
  3. response = session.get(url)
复制代码
在这里附上一张B站的xml弹幕内容详解的图,方便大家查阅:

拿到xml的内容后,对xml文件进行解析
  1. stimes = []                # 弹幕出现时间(单位:秒)
  2. dates = []                 # 弹幕发送时间
  3. uhashs = []                # 弹幕发送者uid的crc32
  4. dmids = []                # 弹幕id(用于标注弹幕顺序,历史弹幕,举报大幕等功能)
  5. dm_texts = []        # 弹幕文本
  6. # 解析xml数据
  7. xml = etree.fromstring(response.content)
  8. dms = xml.xpath("/i/d")
  9. for dm in dms:
  10.     dm_attr = "".join(dm.xpath("./@p"))  # 弹幕属性
  11.     dm_text = "".join(dm.xpath("./text()"))  # 弹幕文本
  12.     """
  13.     弹幕格式:
  14.         <d p="{stime},{mode},{size},{color},{date},{pool},{uhash},{dmid},{weight}">
  15.           {text}
  16.         </d>
  17.     """
  18.     dm_attrs = dm_attr.split(",")
  19.     stime = dm_attrs[0]     
  20.     date = int(dm_attrs[4])     
  21.     uhash = dm_attrs[6]     
  22.     dmid = dm_attrs[7]      
  23.     # 拼接
  24.     stimes.append(stime)
  25.     dt = datetime.datetime.fromtimestamp(date)
  26.     date = dt.strftime('%Y-%m-%d %H:%M:%S')
  27.     dates.append(date)
  28.     uhashs.append(uhash)
  29.     dmids.append(f"'{dmid}")
  30.     dm_texts.append(dm_text)
复制代码
保存为excel文件时,这里有个点要强调一下,如果文件存在的话,是不需要写入表头的,否则会造成如下结果:

这里我写了一个方法,直接调用就可以将数据保存为csv文件了:
  1. def save_to_csv(dms, csv_name):
  2.     """
  3.     数据保存到csv
  4.     @param dms: 弹幕列表数据
  5.     @param csv_name: csv文件名字
  6.     @return:
  7.     """
  8.     # 把列表转换成 dataframe
  9.     dm_df = pd.DataFrame(dms)
  10.     # 判断文件是否存在
  11.     if not os.path.exists(csv_name):
  12.         # 如果文件不存在,写入数据并包含表头 (如果乱码,可以尝试将编码设置成:utf_8_sig)
  13.         dm_df.to_csv(csv_name, mode='w', encoding='utf_8_sig', header=True, index=False)
  14.     else:
  15.         # 如果文件存在,追加数据并省略表头 (如果乱码,可以尝试将编码设置成:utf_8_sig)
  16.         dm_df.to_csv(csv_name, mode='a', encoding='utf_8_sig', header=False, index=False)
复制代码
来看下爬虫程序运行后最终得到的excel文档数据:黑神话悟空弹幕.csv

黑神话弹幕情感分析

整体思路

1、使用jieba分词,统计TOP10高频词
2、使用SnowNLP给弹幕内容打标:积极、消极,并统计占比情况
3、使用wordcloud绘制黑神话悟空弹幕词云图
在编写爬虫代码之前,先导入我们必须用到的包
  1. import jieba.analyse                # 结巴分词
  2. import jieba.posseg as pseg # 结巴分词
  3. from wordcloud import WordCloud, random_color_func     # 词云
  4. import numpy as np
  5. from PIL import Image        # 图像处理
  6. import pandas as pd  # 存取csv
复制代码
统计TOP10热门高频词

首先,我们需要读取刚刚我们获得的csv文件
  1. # 读取csv文件
  2. df = pd.read_csv("黑神话悟空弹幕.csv", encoding="utf8")
  3. # 弹幕内容
  4. danmu_texts = df["弹幕内容"].values.tolist()
  5. dm_str = " ".join(danmu_texts)
  6. print(f"总弹幕条数:{len(danmu_texts)}")
复制代码
然后我们使用jieba分词,进行词性过滤,只保留名词(n)和形容词(a),避免介词等对我们的数据造成干扰
  1. # jieba分词
  2. words_list = pseg.cut(dm_str)
  3. # 词性过滤:只保留名词(n)和形容词(a)
  4. filtered_words = [word for word, flag in words_list if flag in ('n', 'a')]
  5. words_str = ' '.join(filtered_words)
  6. print(f"结巴分词结果:{words_str}")
复制代码
最后,我们使用jieba.analyse.extract_tag这个方法统计一下黑神话悟空弹幕的TOP10高频词
  1. # 统计TOP10高频词
  2. top10_keywords = jieba.analyse.extract_tags(words_str, withWeight=True, topK=10)
  3. print(f"TOP10高频关键词:{top10_keywords}")
复制代码
看下输出结果:

情感分析打标

安装snownlp库
  1. # SnowNLP是一个python写的类库,可以方便的处理中文文本内容,是受到了TextBlob的启发而写的
  2. pip install snownlp
复制代码
然后我们来简单的看一下这个库是如何使用的:
  1. from snownlp import SnowNLP
  2. word = u'这个姑娘真漂亮!'
  3. s = SnowNLP(word)
  4. print(s.words)        # 分词
  5. print(list(s.tags))   # 词性标注
  6. print(s.sentiments)   # 情感分数
  7. print(s.pinyin)       # 拼音
  8. print(SnowNLP(u'蒹葭蒼蒼,白露為霜。所謂伊人,在水一方。').han)  # 繁体字转简体
  9. # 运行结果如下:
  10. ['这个', '姑娘', '真', '漂亮', '!']
  11. [('这个', 'r'), ('姑娘', 'n'), ('真', 'd'), ('漂亮', 'a'), ('!', 'w')]
  12. 0.9704576746581126
  13. ['zhe', 'ge', 'gu', 'niang', 'zhen', 'piao', 'liang', '!']
  14. 蒹葭苍苍,白露为霜。所谓伊人,在水一方。
复制代码
接着我们来为黑神话悟空的弹幕写一个情感分析的函数,方便直接调用。
  1. def emotion_analyse(danmu_texts, out_file_path):
  2.     """
  3.     情感分析打分
  4.     @param danmu_texts: 弹幕列表
  5.     @param out_file_path: 输出文件
  6.     @return:
  7.     """
  8.     scores = []  # 情感评分值
  9.     tags = []  # 打标分类结果
  10.     pos_count = 0  # 计数器-积极
  11.     neg_count = 0  # 计数器-消极
  12.     for danmu_text in danmu_texts:
  13.         # 获得该条弹幕的情感分数
  14.         emotion_score = SnowNLP(danmu_text).sentiments
  15.         if emotion_score < 0.3:
  16.           tag = '消极'    # 如果分数 < 0.3 我们认为他是消极的
  17.           neg_count += 1
  18.         else:
  19.           tag = '积极'    # 如果分数 >= 0.3 我们认为他是积极的
  20.           pos_count += 1
  21.         scores.append(emotion_score)  # 得分值
  22.         tags.append(tag)  # 打标分类
  23.     print('积极评价占比:', round(pos_count / (pos_count + neg_count), 4))
  24.     print('消极评价占比:', round(neg_count / (pos_count + neg_count), 4))
  25.     # 放到表格里
  26.     df['情感得分'] = scores
  27.     df['分析结果'] = tags
  28.     # 把情感分析结果保存到新的excel文件
  29.     df.to_csv(out_file_path, index=False)
复制代码
调用后,得到了如下情感分析的csv文件(最后两列,是情感得分和分析结果)

从下面的最终占比结果中可以看出:83%的弹幕都是积极向上的肯定评论,也说明了这款游戏确实得到了广泛的认可。

词云图生成

注意!注意!注意!
作为词云图的背景底图,下面的代码要求必须是白色背景或透明背景的(实在找不到的话,就只能用ps软件处理一下了),否则生成的词云图是满屏的!!
  1. def generate_word_cloud(words_str, stop_words, background_image_path, out_file_path):
  2.     """
  3.     生成词云
  4.     @param words_str: 文本内容
  5.     @param stop_words: 停用词
  6.     @param background_image_path: 背景图路径
  7.     @param out_file_path: 词云图输出文件路径
  8.     @return:
  9.     """
  10.     # 读取背景底图
  11.     backgroud_image = np.array(Image.open(background_image_path))
  12.     # 创建词云
  13.     wc = WordCloud(
  14.         background_color='white',   # 背景颜色
  15.         mask=backgroud_image,   # 背景图
  16.         font_path='C:\Windows\Fonts\msyh.ttc',  # 字体文件路径,根据实际情况(Windows)替换
  17.         max_words=2000, # 最多字数
  18.         color_func=random_color_func,  # 随机文字颜色
  19.         stopwords=stop_words,
  20.         contour_width=1,        # 添加1px的轮廓线
  21.         contour_color='steelblue',      # 轮廓线的颜色
  22.         # width=1500, # 图宽
  23.         # height=1200,    # 图高
  24.         # max_font_size=100,  # 最大字体大小
  25.         # min_font_size=10,   # 最小字体大小
  26.         # random_state=5,    # 随机数种子(如果不指定,则生成的词云图布局具有随机性;如果指定,则每次生成的词云图布局都是确定的)
  27.     )
  28.     # 生成词云图
  29.     wc.generate(words_str)
  30.     # 保存图片文件
  31.     wc.to_file(out_file_path)
复制代码
词云图绘制结果:因为我上面添加了1px的轮廓线,所以会有下面图上的人物边缘线

和原始图对比:

弹幕情感分析总结


  • 打标结果:积极占比0.8322,消极占比0.1678,远远高于消极评论!
  • top10热门高频词统计结果:"二郎神"、"猴子"、"猴哥"等是大家非常关注的对象!"卧槽"、"太帅"等情绪词也表明了对游戏的肯定!
  • 词云图中:"好"、"太帅"等好评词也反映了观众的积极情绪!
综上所述,经分析"黑神话悟空"相关弹幕,可以得出结论:
众多网友对黑神话悟空的评价都很高,也很喜欢这款游戏大作,不仅游戏画质高,还能将中国传统文化传播到全世界!
致敬!
获取python完整源码

我是@王哪跑,持续分享python干货,各类副业技巧及软件!
附完整python源码及csv表格数据:B站黑神话悟空热门弹幕情感分析及词云生成

来源:https://www.cnblogs.com/wangnp/p/18464405
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具