行业知识
B站热门视频弹幕情感分析(含B站视频弹幕爬虫,可用于爬取任意视频的弹幕)已修改,可直接运行
目录
1,源代码
源代码使用指南
爬虫
预处理 - 此部分是应付老师的只是把预处理这一步单独提取出来了
分析1 情感得分统计
分析2 词云图绘制
停用词参考(stopwords.txt)
2,总结
3,爬虫优化
1,源代码
源代码使用指南
爬虫
将url修改为自己想要分析的视频的url
分析1/分析2
在爬取完数据之后直接运行即可
注意
预处理可以省去
这五个文件要在同一目录下
爬虫
#!/usr/bin/env python3# -*- coding:utf-8 -*-# @author JourWon# @date 2024/5/4# @file 爬虫.py# 根据视频url爬取弹幕import requestsimport osimport reimport csvfrom lxml import etreeheaders = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36 Edg/114.0.1823.37'}url_video = 'https://www.bilibili.com/video/BV1e24y1D7qt/?spm_id_from=333.999.0.0'# 获取弹幕urla = url_videob = 'i'str_list = list(a)str_list.insert(12, b)url_danmu = ''.join(str_list)r = requests.get(url=url_danmu, headers=headers)r.encoding = r.apparent_encodingtree = etree.HTML(r.text)video_name = tree.xpath('//p[@]/h4/text()')[0]url = tree.xpath('//p[@]/p[2]/p[5]/input/@value')[0]r = requests.get(url=url, headers=headers)r.encoding = r.apparent_encodingtext_list = re.findall('(.*?)', r.text)for i in range(0, len(text_list)): text_list[i] = [text_list[i]]fileName = '弹幕'if not os.path.exists('./' + fileName): os.mkdir('./' + fileName)headers = ['弹幕']rows = text_listwith open('./' + fileName + '/' + video_name + '_弹幕信息.csv', 'w', encoding='utf-8', newline='') as f: writer = csv.writer(f) writer.writerow(headers) writer.writerows(rows) print(video_name + '共', len(text_list), '条弹幕下载成功!') 预处理 - 此部分是应付老师的只是把预处理这一步单独提取出来了
# 预处理import pandas as pdimport reimport jiebafrom collections import Counterimport os# 读取csv文件file_dir = DPyCharmpythonProject课设木鱼水浒弹幕 # file directoryall_csv_list = os.listdir(file_dir) # get csv listk = 0for single_csv in all_csv_list st = file_dir + '' + single_csv print(k) k = k + 1 print(st) single_data_frame = pd.read_csv(st) if single_csv == all_csv_list[0] data = single_data_frame else # concatenate all csv to a single dataframe, ingore index data = pd.concat([data, single_data_frame], ignore_index=True) # # 读取csv文件# df = pd.read_csv(DPyCharmpythonProject课设b站弹幕all.csv)# 删除评论内容列中的空格和无效字符data['弹幕'] = data['弹幕'].str.replace(r's+', '')# 将该列中的所有元素强制转换为字符串类型data['弹幕'] = data['弹幕'].astype(str)data.columns = ['comment']# 过滤无用评论stopwords = ['哈哈', '什么', '哈哈哈', '6']pattern = ''.join(stopwords)data = data[-data['comment'].str.contains(pattern)]# 分词和去重cut_comments = []for comment in data['comment'] words = [word for word in jieba.cut(comment) if word.strip()] cut_comments.append(words)# 去除停用词stopwords = ['的', '了', '啊', '吗', '呀', '呢', '额', '还','也', ',', '。', '!', '?', ':']cut_comments = [[word for word in words if word not in stopwords] for words in cut_comments]# 保存处理后数据到新csv文件new_data = pd.DataFrame(cut_comments)new_data.to_csv('水浒.csv', encoding='utf-8', index=False) 分析1 情感得分统计
#!/usr/bin/env python3# -*- coding:utf-8 -*-# @author JourWon# @date 2024/5/4# @file 分析情感得分.py# 词云直方图一个csv文件夹一张图import pandas as pdimport osfrom snownlp import SnowNLPimport matplotlib as mpl# 配置之后便可使用mpl.rcParams['font.family'] = 'SimHei'mpl.rcParams['font.sans-serif'] = ['SimHei']mpl.rcParams['axes.unicode_minus'] = Falsefrom matplotlib import pyplot as pltfile_dir = "./弹幕/" # file directoryall_csv_list = os.listdir(file_dir) # get csv listk = 0for single_csv in all_csv_list: st = file_dir + '/' + single_csv print(k) k = k + 1 print(st) single_data_frame = pd.read_csv(st) if single_csv == all_csv_list[0]: df = single_data_frame else: # concatenate all csv to a single dataframe, ingore index df = pd.concat([df, single_data_frame], ignore_index=True)# 删除评论内容列中的空格和无效字符df['弹幕'] = df['弹幕'].str.replace(r'\s+', '')# 将该列中的所有元素强制转换为字符串类型df['弹幕'] = df['弹幕'].astype(str)# 对评论内容列进行情感分析sentiment = df['弹幕'].apply(lambda x: SnowNLP(x).sentiments)# 绘制情感得分直方图plt.hist(sentiment, bins=30, alpha=0.5, color='steelblue')# 添加标题和标签plt.title('情感得分直方图')plt.xlabel('情感得分')plt.ylabel('评论数量')# 显示图形plt.show() 分析2 词云图绘制
#!/usr/bin/env python3# -*- coding:utf-8 -*-# @author JourWon# @date 2024/5/4# @file 分析弹幕词云图绘制.py# 词云直方图一个csv一张图import pandas as pdimport osimport jiebafrom snownlp import SnowNLPfrom wordcloud import WordCloudimport matplotlib as mpl# 配置之后便可使用mpl.rcParams['font.family'] = 'SimHei'mpl.rcParams['font.sans-serif'] = ['SimHei']mpl.rcParams['axes.unicode_minus'] = Falsefrom matplotlib import pyplot as pltplt.xlabel('X轴标签')plt.ylabel('Y轴标签')plt.title('标题')file_dir = "./弹幕/" # file directoryall_csv_list = os.listdir(file_dir) # get csv listk = 0for single_csv in all_csv_list: st = file_dir + '/' + single_csv print(k) k = k + 1 print(st) df = pd.read_csv(st) # 删除评论内容列中的空格和无效字符 df['弹幕'] = df['弹幕'].str.replace(r'\s+', '') # 将该列中的所有元素强制转换为字符串类型 df['弹幕'] = df['弹幕'].astype(str) stopwords_path = "stopwords.txt" # 停用词路径 stopwords = set(open(stopwords_path, encoding='utf-8').read().splitlines()) # 读取停用词 text_list = [] for content in df['弹幕']: seg_list = jieba.cut(content) # 分词 seg_list = [i for i in seg_list if i not in stopwords] # 去除停用词 text_list.extend(seg_list) # 绘制词云图 text = ' '.join(text_list) wordcloud = WordCloud(font_path='simhei.ttf', background_color='white', width=800, height=600).generate(text) plt.imshow(wordcloud) plt.axis("off") plt.show() # 对评论内容列进行情感分析 sentiment = df['弹幕'].apply(lambda x: SnowNLP(x).sentiments) # 绘制情感得分直方图 plt.hist(sentiment, bins=30, alpha=0.5, color='steelblue') # 添加标题和标签 plt.title('情感得分直方图') plt.xlabel('情感得分') plt.ylabel('评论数量') # 显示图形 plt.show() 停用词参考(stopwords.txt)
!"#$%&'()*+,---................................/.一.数.日///0123456789:://::;>>?@ALex[\]^_`expsubsup|}~~~~~·××××ΔΨγμφφ.В——————‘’’‘“””,…………………………………………………………③′∈′|℃Ⅲ↑→∈[∪φ∈≈①②②c③③]④⑤⑥⑦⑧⑨⑩──■▲ 、。〈〉《》》),」『』【】〔〕〕〔㈧一一.一一一下一个一些一何一切一则一则通过一天一定一方面一旦一时一来一样一次一片一番一直一致一般一起一转眼一边一面七万一三三天两头三番两次三番五次上上下上升上去上来上述上面下下列下去下来下面不不一不下不久不了不亦乐乎不仅不仅...而且不仅仅不仅仅是不会不但不但...而且不光不免不再不力不单不变不只不可不可开交不可抗拒不同不外不外乎不够不大不如不妨不定不对不少不尽不尽然不巧不已不常不得不得不不得了不得已不必不怎么不怕不惟不成不拘不择手段不敢不料不断不日不时不是不曾不止不止一次不比不消不满不然不然的话不特不独不由得不知不觉不管不管怎样不经意不胜不能不能不不至于不若不要不论不起不足不过不迭不问不限与与其与其说与否与此同时专门且且不说且说两者严格严重个个人个别中小中间丰富串行临临到为为主为了为什么为什麽为何为止为此为着主张主要举凡举行乃乃至乃至于么之之一之前之后之後之所以之类乌乎乎乒乘乘势乘机乘胜乘虚乘隙九也也好也就是说也是也罢了了解争取二二来二话不说二话没说于于是于是乎云云云尔互互相五些交口亦产生亲口亲手亲眼亲自亲身人人人人们人家人民什么什么样什麽仅仅仅今今后今天今年今後介于仍仍旧仍然从从不从严从中从事从今以后从优从古到今从古至今从头从宽从小从新从无到有从早到晚从未从来从此从此以后从而从轻从速从重他他人他们他是他的代替以以上以下以为以便以免以前以及以后以外以後以故以期以来以至以至于以致们任任何任凭任务企图伙同会伟大传传说传闻似乎似的但但凡但愿但是何何乐而不为何以何况何处何妨何尝何必何时何止何苦何须余外作为你你们你是你的使使得使用例如依依据依照依靠便便于促进保持保管保险俺俺们倍加倍感倒不如倒不如说倒是倘倘使倘或倘然倘若借借以借此假使假如假若偏偏做到偶尔偶而傥然像儿允许元/吨充其极充其量充分先不先先后先後先生光光是全体全力全年全然全身心全部全都全面八八成公然六兮共共同共总关于其其一其中其二其他其余其后其它其实其次具体具体地说具体来说具体说来具有兼之内再再其次再则再有再次再者再者说再说冒冲决不决定决非况且准备凑巧凝神几几乎几度几时几番几经凡凡是凭凭借出出于出去出来出现分别分头分期分期分批切切不可切切切勿切莫则则甚刚刚好刚巧刚才初别别人别处别是别的别管别说到到了儿到处到头到头来到底到目前为止前后前此前者前进前面加上加之加以加入加强动不动动辄勃然匆匆十分千千万千万千万半单单单单纯即即令即使即便即刻即如即将即或即是说即若却却不历原来去又又及及及其及时及至双方反之反之亦然反之则反倒反倒是反应反手反映反而反过来反过来说取得取道受到变成古来另另一个另一方面另外另悉另方面另行只只当只怕只是只有只消只要只限叫叫做召开叮咚叮当可可以可好可是可能可见各各个各人各位各地各式各种各级各自合理同同一同时同样后后来后者后面向向使向着吓吗否则吧吧哒吱呀呃呆呆地呐呕呗呜呜呼呢周围呵呵呵呸呼哧呼啦咋和咚咦咧咱咱们咳哇哈哈哈哉哎哎呀哎哟哗哗啦哟哦哩哪哪个哪些哪儿哪天哪年哪怕哪样哪边哪里哼哼唷唉唯有啊啊呀啊哈啊哟啐啥啦啪达啷当喀喂喏喔唷喽嗡嗡嗡嗬嗯嗳嘎嘎嘎嘎登嘘嘛嘻嘿嘿嘿四因因为因了因此因着因而固固然在在下在于地均坚决坚持基于基本基本上处在处处处理复杂多多么多亏多多多多少少多多益善多少多年前多年来多数多次够瞧的大大不了大举大事大体大体上大凡大力大多大多数大大大家大张旗鼓大批大抵大概大略大约大致大都大量大面儿上失去奇奈奋勇她她们她是她的好好在好的好象如如上如上所述如下如今如何如其如前所述如同如常如是如期如果如次如此如此等等如若始而姑且存在存心孰料孰知宁宁可宁愿宁肯它它们它们的它是它的安全完全完成定实现实际宣布容易密切对对于对应对待对方对比将将才将要将近小少数尔尔后尔尔尔等尚且尤其就就地就是就是了就是说就此就算就要尽尽可能尽如人意尽心尽力尽心竭力尽快尽早尽然尽管尽管如此尽量局外居然届时属于屡屡屡屡次屡次三番岂岂但岂止岂非川流不息左右巨大巩固差一点差不多己已已矣已经巴巴巴带帮助常常常常言说常言说得好常言道平素年复一年并并不并不是并且并排并无并没并没有并肩并非广大广泛应当应用应该庶乎庶几开外开始开展引起弗弹指之间强烈强调归归根到底归根结底归齐当当下当中当儿当前当即当口儿当地当场当头当庭当时当然当真当着形成彻夜彻底彼彼时彼此往往往待待到很很多很少後来後面得得了得出得到得天独厚得起心里必必定必将必然必要必须快快要忽地忽然怎怎么怎么办怎么样怎奈怎样怎麽怕急匆匆怪怪不得总之总是总的来看总的来说总的说来总结总而言之恍然恐怕恰似恰好恰如恰巧恰恰恰恰相反恰逢您您们您是惟其惯常意思愤然愿意慢说成为成年成年累月成心我我们我是我的或或则或多或少或是或曰或者或许战斗截然截至所所以所在所幸所有所谓才才能扑通打打从打开天窗说亮话扩大把抑或抽冷子拦腰拿按按时按期按照按理按说挨个挨家挨户挨次挨着挨门挨户挨门逐户换句话说换言之据据实据悉据我所知据此据称据说掌握接下来接着接著接连不断放量故故意故此故而敞开儿敢敢于敢情数/整个断然方方便方才方能方面旁人无无宁无法无论既既...又既往既是既然日复一日日渐日益日臻日见时候昂然明显明确是是不是是以是否是的显然显著普通普遍暗中暗地里暗自更更为更加更进一步曾曾经替替代最最后最大最好最後最近最高有有些有关有利有力有及有所有效有时有点有的有的是有着有著望朝朝着末##末本本人本地本着本身权时来来不及来得及来看来着来自来讲来说极极为极了极其极力极大极度极端构成果然果真某某个某些某某根据根本格外梆概次第欢迎欤正值正在正如正巧正常正是此此中此后此地此处此外此时此次此间殆毋宁每每个每天每年每当每时每刻每每每逢比比及比如比如说比方比照比起比较毕竟毫不毫无毫无例外毫无保留地汝沙沙没没奈何没有沿沿着注意活深入清楚满满足漫说焉然然则然后然後然而照照着牢牢特别是特殊特点犹且犹自独独自猛然猛然间率尔率然现代现在理应理当理该瑟瑟甚且甚么甚或甚而甚至甚至于用用来甫甭由由于由是由此由此可见略略为略加略微白白白的的确的话皆可目前直到直接相似相信相反相同相对相对而言相应相当相等省得看看上去看出看到看来看样子看看看见看起来真是真正眨眼着着呢矣矣乎矣哉知道砰确定碰巧社会主义离种积极移动究竟穷年累月突出突然窃立立刻立即立地立时立马竟竟然竟而第第二等等到等等策略地简直简而言之简言之管类如粗精光紧接着累年累次纯纯粹纵纵令纵使纵然练习组成经经常经过结合结果给绝绝不绝对绝非绝顶继之继后继续继而维持综上所述缕缕罢了老老大老是老老实实考虑者而而且而况而又而后而外而已而是而言而论联系联袂背地里背靠背能能否能够腾自自个儿自从自各儿自后自家自己自打自身臭至至于至今至若致般的良好若若夫若是若果若非范围莫莫不莫不然莫如莫若莫非获得藉以虽虽则虽然虽说蛮行为行动表明表示被要要不要不是要不然要么要是要求见规定觉得譬喻譬如认为认真认识让许多论论说设使设或设若诚如诚然话说该该当说明说来说说请勿诸诸位诸如谁谁人谁料谁知谨豁然贼***赖以赶赶快赶早不赶晚起起先起初起头起来起见起首趁趁便趁势趁早趁机趁热趁着越是距跟路经转动转变转贴轰然较较为较之较比边达到达旦迄迅速过过于过去过来运用近近几年来近年来近来还还是还有还要这这一来这个这么这么些这么样这么点儿这些这会儿这儿这就是说这时这样这次这点这种这般这边这里这麽进入进去进来进步进而进行连连同连声连日连日来连袂连连迟早迫于适应适当适用逐步逐渐通常通过造成逢遇到遭到遵循遵照避免那那个那么那么些那么样那些那会儿那儿那时那末那样那般那边那里那麽部分都鄙人采取里面重大重新重要鉴于针对长期以来长此下去长线长话短说问题间或防止阿附近陈年限制陡然除除了除却除去除外除开除此除此之外除此以外除此而外除非随随后随时随着随著隔夜隔日难得难怪难说难道难道说集中零需要非但非常非徒非得非特非独靠顶多顷顷刻顷刻之间顷刻间顺顺着顿时颇风雨无阻饱首先马上高低高兴默然默默地齐︿!#$%&'())÷(1-)、*++ξ++,,也--β---[*]-./00:211.12%22.3%3455:06789:;<<±<Δ<λ<φ<<==″=☆=(=-=[={>>λ?@ALIR.L.ZXFITL[[①①][①②][①③][①④][①⑤][①⑥][①⑦][①⑧][①⑨][①A][①B][①C][①D][①E][①][①a][①c][①d][①e][①f][①g][①h][①i][①o][②[②①][②②][②③][②④[②⑤][②⑥][②⑦][②⑧][②⑩][②B][②G][②][②a][②b][②c][②d][②e][②f][②g][②h][②i][②j][③①][③⑩][③F][③][③a][③b][③c][③d][③e][③g][③h][④][④a][④b][④c][④d][④e][⑤][⑤]][⑤a][⑤b][⑤d][⑤e][⑤f][⑥][⑦][⑧][⑨][⑩][*][-[]]]∧′=[][_a]b]c]e]f]ng昉{{-|}}>~~±~+¥
2,总结
随着自媒体时代的兴起和视频分享网站的普及,弹幕成为了一种流行的实时评论形式。在哔哩哔哩弹幕视频网站,弹幕语言的作用不容小觑。弹幕作为一种实时评论,涵盖了用户观看视频时的情感和看法,成为了视频内容的反馈和补充,丰富了视频制作和观看的体验。
在本次项目中,以B站著名UP主木鱼水心的水浒传合集共50个分P的全部弹幕数据为对象,爬取了大量的弹幕数据,并对其进行了清洗等预处理,去除了无效的数据。最后使用matplotlib对弹幕文本进行情感分析并绘制了词云图。
通过对B站弹幕文本进行情感倾向的分析,我们可以从整体上把握视频的情感分布,从而更好地理解和分析观众对这部经典作品的评价和反应。同时,观众可以根据视频的情感分布来选择自己想看的视频,在B站选取适合自己的视频;B站 UP主可以根据视频的情感分布来改进自己的视频制作,向更多用户传达自己的意图,提高视频质量;B站也可以根据用户的弹幕分析来优化推荐算法,推荐更符合用户兴趣和情感倾向的视频内容。
在这个数字化时代,数据分析和处理已经成为各行各业中不可或缺的一部分,同样也在视频制作和观看中起到了重要的作用。通过对B站弹幕文本进行情感分析,我们可以从不同的角度探索视频的内涵和价值,并为B站用户和UP主提供更加全面和专业的服务。
同时,本次项目也对情感分析技术的应用提出了一些思考。情感分析技术可以帮助我们更加深入地了解人们的情感表达和反应,但同时也面临着一系列的挑战。比如,情感的表达与理解具有一定的主观性,需要准确地进行语义分析与推断;同时,网络上的弹幕文本通常存在着大量的文本噪声和口头语言等特殊情况,这也需要我们对数据进行更加精细的预处理和清洗。因此,我们需要不断地优化情感分析算法和技术手段,从而更好地挖掘视频数据和用户反馈,为用户提供更好的服务。
3,爬虫优化
将爬虫封装,
# 指定视频的url自动爬取弹幕
# 指定filename爬取到的数据将会保存到文件同一目录下的filename目录下,文件名称为 视频标题
# 例如:url_video = 'https://www.bilibili.com/video/BV1e24y1D7qt/?spm_id_from=333.999.0.0'
# fileName = '木鱼水浒弹幕'
# 保存路径为 ./木鱼水浒弹幕/终了!荡气回肠!水浒传结局好在哪儿?《水浒传》P50-终了!荡气回肠!水浒传结局好在哪儿?《水浒传》P50_弹幕信息.csv
import requestsimport osimport reimport csvfrom lxml import etree# 指定视频的url自动爬取弹幕# 指定filename爬取到的数据将会保存到文件同一目录下的filename目录下,文件名称为 视频标题# 例如:url_video = 'https://www.bilibili.com/video/BV1e24y1D7qt/?spm_id_from=333.999.0.0'# fileName = '木鱼水浒弹幕'# 保存路径为 ./木鱼水浒弹幕/终了!荡气回肠!水浒传结局好在哪儿?《水浒传》P50-终了!荡气回肠!水浒传结局好在哪儿?《水浒传》P50_弹幕信息.csvdef pachong(url_video,fileName): headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36 Edg/114.0.1823.37' } # 获取弹幕url a = url_video b = 'i' str_list = list(a) str_list.insert(12, b) url_danmu = ''.join(str_list) r = requests.get(url=url_danmu, headers=headers) r.encoding = r.apparent_encoding tree = etree.HTML(r.text) video_name = tree.xpath('//p[@]/h4/text()')[0] url = tree.xpath('//p[@]/p[2]/p[5]/input/@value')[0] r = requests.get(url=url, headers=headers) r.encoding = r.apparent_encoding text_list = re.findall('(.*?)', r.text) for i in range(0, len(text_list)): text_list[i] = [text_list[i]] if not os.path.exists('./' + fileName): os.mkdir('./' + fileName) headers = ['弹幕'] rows = text_list with open('./' + fileName + '/' + video_name + '_弹幕信息.csv', 'w', encoding='utf-8', newline='') as f: writer = csv.writer(f) writer.writerow(headers) writer.writerows(rows) print(video_name + '共', len(text_list), '条弹幕下载成功!')