作者
皖渝
出品
凹凸数据(ID:alltodata)
头图
CSDN 下载自东方IC
爬取介绍
利用 Chrome 浏览器抓包可知,B站的弹幕文件以 XML 文档式进行储存,如下所示(共三千条实时弹幕)
其 URL 为:http://comment.bilibili.com/183362119.xml
数字183362119则代表该视频专属 ID ,通过改变数字即可得到相应的弹幕文件。打开第1集的视频,查看源码,如下图所示。
不难看出,CID 则是对应着各个视频的 ID,接下来用正则提取即可。
完整爬取代码如下
import requestsimport refrom bs4 import BeautifulSoup as BSimport ospath=C:/Users/dell/Desktop/柯南if os.path.exists(path)==False: os.makedirs(path)os.chdir(path)
def gethtml(url,header): r=requests.get(url,headers=header) r.encoding=utf-8 return r.text
def crawl_comments(r_text): txt1=gethtml(url,header) pat="cid":(\d+) chapter_total=re.findall(pat,txt1)[1:-2] count=1 for chapter in chapter_total: url_base=http://comment.bilibili.com/{}.xml.format(chapter) txt2=gethtml(url_base,header) soup=BS(txt2,lxml) all_d=soup.find_all(d) with open({}.txt.format(count),w,encoding=utf-8) as f: for d in all_d: f.write(d.get_text+\n) print(第{}话弹幕写入完毕.format(count)) count+=1
if __name__==__main__: url=https://www.bilibili.com/bangumi/play/ep321808 header={user-agent:Opera/12.80 (Windows NT 5.1; U; en) Presto/2.10.289 Version/12.02} r_text=gethtml(url,header) crawl_comments(r_text)最终的全部弹幕文件都在桌面的"柯南"文件下
注:这里共爬取到980个弹幕文件。【B站的柯南自941集后就跳到994集(大会员才能观看的)。虽然目前更新到1032话,但并没有1032集内容,如下图所示】
弹幕可视化
1、主要人物讨论总次数分析
统计人数总次数
注:role.txt 是主要人物名文件(需考虑到弹幕一般不会对人物的全名进行称呼,多数使用的是昵称,否则可能与实际情况相差较大。)
import jiebaimport osimport pandas as pdos.chdir(C:/Users/dell/Desktop)jieba.load_userdict(role.txt)role=[ i.replace(\n,) for i in open(role.txt,r,encoding=utf-8).readlines()]txt_all=os.listdir(./柯南/)txt_all.sort(key=lambda x:int(x.split(.)[0])) #按集数排序count=1def role_count:df = pd.DataFrame for chapter in txt_all: names={} data= with open(./柯南/{}.format(chapter),r,encoding=utf-8) as f: for line in f.readlines: poss=jieba.cut(line) for word in poss: if word in role: if names.get(word) is None: names[word]=0 names[word]+=1 df_new = pd.DataFrame.from_dict(names,orient=index,columns=[{}.format(count)]) df = pd.concat([df,df_new],axis=1) print(第{}集人物统计完毕.format(count)) count+=1df.T.to_csv(role_count.csv,encoding=gb18030)可视化
import numpy as npimport matplotlib.pyplot as pltplt.rcParams[font.sans-serif]=[kaiti]plt.style.use(ggplot)df=pd.read_csv(role_count.csv,encoding=gbk)df=df.fillna(0).set_index(episode)plt.figure(figsize=(10,5))role_sum=df.sum.to_frame.sort_values(by=0,ascing=False)g=sns.barplot(role_sum.index,role_sum[0],palette=Set3,alpha=0.8)index=np.arange(len(role_sum))for name,count in zip(index,role_sum[0]): g.text(name,count+50,int(count),ha=center,va=bottom,)plt.title(B站名侦探柯南弹幕——主要人物讨论总次数分布)plt.ylabel(讨论次数)plt.show虽说是万年小学生,柯南还是有变回新一的时候,且剧情也并不只是"找犯人—抓犯人"。接下来从数据的角度来,扒扒一些精彩剧情集数。
2、柯南变回新一集数统计
考虑到部分集数中新一是在回忆中出现的,为减少偏差,将讨论的阈值设为250次,绘制如下分布图
其讨论次数结果及剧集名如下表所示
有兴趣的朋友可以码一下,除235集外,均是柯南变回新一的集数。
相关代码如下:
df=pd.read_csv(role_count.csv,encoding=gbk)df=df.fillna(0).set_index(episode)xinyi=df[df[新一]>=250][新一].to_frameprint(xinyi) #新一登场集数plt.figure(figsize=(10,5))plt.plot(df.index,df[新一],label=新一,color=blue,alpha=0.6)plt.annotate(集数:50,讨论次数:309, xy=(50,309), xytext=(40,330), arrowprops=dict(color=red,headwidth=8,headlength=8) )plt.annotate(集数:206,讨论次数:263, xy=(206,263), xytext=(195,280), arrowprops=dict(color=red,headwidth=8,headlength=8) )plt.annotate(集数:571,讨论次数:290, xy=(571,290), xytext=(585,310), arrowprops=dict(color=red,headwidth=8,headlength=8) )plt.hlines(xmin=df.index.min,xmax=df.index.max,y=250,linestyles=--,colors=red)plt.leg(loc=best,frameon=False)plt.xlabel(集数)plt.ylabel(讨论次数)plt.title(工藤新一讨论次数分布图)plt.show以讨论次数最多的572集,绘制词云图(剔除了高频词"新一",防止遗漏其他信息)如下所示:
从图中可看出,出现频率较高地词有整容、服部、声音、爱情等。(看来凶手是整成了新一的模样进行犯罪的,还有新兰的感情戏在里面,值得一看)
3、主线集数内容分析
主线剧情主要是围绕着组织成员(琴酒、伏特加、贝尔摩德)展开,绘制分布图如下:
plt.figure(figsize=(10,5))names=[琴酒,伏特加,贝姐]colors=[#090707,#004e66,#EC7357]alphas=[0.8,0.7,0.6]for name,color,alpha in zip(names,colors,alphas): plt.plot(df.index,df[name],label=name,color=color,alpha=alpha)plt.leg(loc=best,frameon=False)plt.annotate(集数:{},讨论次数:{}. format(df[贝姐].idxmax,int(df[贝姐].max)), xy=(df[贝姐].idxmax,df[贝姐].max), xytext=(df[贝姐].idxmax+30,df[贝姐].max), arrowprops=dict(color=red,headwidth=8,headlength=8) )plt.xlabel(集数)plt.ylabel(讨论次数)plt.title(酒厂成员讨论次数分布图)plt.hlines(xmin=df.index.min,xmax=df.index.max,y=200,linestyles=--,colors=red)plt.ylim(0,400)
#输出主线剧集mainline=set(list(df[df[贝姐]>=200].index)+list(df[df[琴酒]>=200].index)) #伏特加可忽略不计print(mainline)从上图分析可知,组织成员的行动基本一致,其中贝姐(贝尔摩德)的人气在三人中是较高的,特别是在375集(与黑暗组织直面对决系列),讨论次数高达379。此外,统计其讨论次数大于200次的集数,结果如下:
以讨论次数最高的375集为内容,绘制词云图(剔除了高频词"贝姐",防止遗漏其他信息)如下
从图中可知,天使、琴酒、干妈、心疼、狙击手等词汇出现频率较高。从词频较低的败北主线中可以看出,这次酒厂行动应该是失败告终。
人物形象网络分析
1、合并 txt 文件
为尽可能反映出弹幕观众对人物形象的描述,考虑到一集弹幕共3000条,为减少运行成本,这里仅选取特定人物讨论次数最多的20集合并后再进行分析。
import osimport pandas as pddf=pd.read_csv(role_count.csv,encoding=gbk)df=df.fillna(0).set_index(episode)huiyuan_ep=list(df.sort_values(by=灰原哀,ascing=False).index[:20])mergefiledir = C:/Users/dell/Desktop/柯南file=open(txt_all.txt,w,encoding=UTF-8) count=0for filename in huiyuan_ep: filepath=mergefiledir+/+str(filename)+.txt for line in open(filepath,encoding=UTF-8): file.writelines(line) file.write(\n) count+=1 print(第{}集写入完毕.format(count))file.close
2、人物形象可视化
借助共现矩阵的思想,即同一句话中出现两个指定的词则计数1。指定起始点 Source 为灰原哀,代码如下所示:(注:其中,stopwods.txt 为停止词文件,role.txt 为人物昵称文件)
import codecsimport csvimport jiebalinesName=names={}relationship={}jieba.load_userdict(role.txt)txt=[ line.strip() for line in open(stopwords.txt,r,encoding=utf-8)]name_list=[ i.replace(\n,) for i in open(role.txt,r,encoding=utf-8).readlines()]
def base(path): with codecs.open(path,r,UTF-8) as f: for line in f.readlines: line=line.replace(\r\n,) poss = jieba.cut(line) linesName.app([]) for word in poss: if word in txt: continue linesName[-1].app(word) if names.get(word) is None: names[word]=0 relationship[word]={} names[word]+=1 return linesName,relationship
def relationships(linesName,relationship,name_list): for line in linesName: for name1 in line: if name1 in name_list: for name2 in line: if name1==name2: continue if relationship[name1].get(name2) is None: relationship[name1][name2]=1 else: relationship[name1][name2]+=1 return relationship
def write_csv(relationship): csv_writer2=open(edges.csv,w,encoding=gb18030) writer=csv.writer(csv_writer2,delimiter=,,lineterminator=\n) writer.writerow([Source,Target,Weight]) for name,edges in relationship.items: for k,v in edges.items: if v>10: writer.writerow([name,k,v]) csv_writer2.close
if __name__==__main__: linesName,relationship=base(txt_all.txt) data=relationships(linesName,relationship,name_list) write_csv(data)将生成的文件导入 Gephi ,得到如下人物形象图
线条越粗的线,代表该人物特征越明显。不难看出,大家对于哀酱的评价主要是美腻、可爱、心疼。
再做一张琴酒的~
哈哈哈,大家对琴酒的评价就比较逗逼了,变态,痴汉,聪明啥都有~
你以为的琴酒,实际上的琴酒(手动滑稽
以上就是本次 python 实战的全部内容~
欢迎大家皖渝的博客:
https://blog.csdn.net/shine4869/article/details/107381791
点分享