前言 本文的文字及圖片來源於網路,僅供學習、交流使用,不具有任何商業用途,版權歸原作者所有,如有問題請及時聯繫我們以作處理。 作者:慄科技 一、爬取介紹 利用Chrome瀏覽器抓包可知,B站的彈幕文件以XML文檔式進行儲存,如下所示(共三千條實時彈幕) 其URL為: http://comment.b ...
前言
本文的文字及圖片來源於網路,僅供學習、交流使用,不具有任何商業用途,版權歸原作者所有,如有問題請及時聯繫我們以作處理。
作者:慄科技
一、爬取介紹
利用Chrome瀏覽器抓包可知,B站的彈幕文件以XML文檔式進行儲存,如下所示(共三千條實時彈幕)
其URL為:
http://comment.bilibili.com/183362119.xml
數字183362119則代表該視頻專屬ID,通過改變數字即可得到相應的彈幕文件。打開第1集的視頻,查看源碼,如下圖所示。
不難看出,CID則是對應著各個視頻的ID,接下來用正則提取即可。
完整爬取代碼如下
import requests
import re
from bs4 import BeautifulSoup as BS
import os
path='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.主要人物討論總次數分析
(1)統計人數總次數
註: role.txt是主要人物名文件(需考慮到彈幕一般不會對人物的全名進行稱呼,多數使用的是昵稱,否則可能與實際情況相差較大。)
import jieba
import os
import pandas as pd
os.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=1
def 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+=1
df.T.to_csv('role_count.csv',encoding='gb18030')
(2)可視化
import numpy as np
import matplotlib.pyplot as plt
plt.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,ascending=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_frame()
print(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.legend(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.legend(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集為內容,繪製詞雲圖(剔除了高頻詞"貝姐",防止遺漏其他信息)如下
從圖中可知,天使、琴酒、乾媽、心疼、狙擊手等辭彙出現頻率較高。從詞頻較低的敗北主線中可以看出,這次酒廠行動應該是失敗告終。