利用python对b站某GPT-4解说视频的近万条弹幕进行爬取、数据挖掘、数据分析、弹幕数量预测及情绪分类
????????
目錄
一、利用Python爬取彈幕
?二、利用幾行代碼直接生成詞云
三、將彈幕屬性和內(nèi)容放入mysql當(dāng)中
?四、分析彈幕在視頻各節(jié)點(diǎn)的數(shù)量
1、分析視頻各個片段出現(xiàn)的彈幕數(shù)量
2、分析視頻各大章節(jié)出現(xiàn)的彈幕數(shù)量
3.分析視頻各小節(jié)出現(xiàn)的彈幕數(shù)量
五、分析彈幕數(shù)量和日期的關(guān)系
1、分析不同日期的彈幕數(shù)量
2、上午、下午、晚上的彈幕數(shù)量
3、每天不同細(xì)分時間段的彈幕數(shù)量
六、利用LSTM網(wǎng)絡(luò)對彈幕數(shù)量進(jìn)行預(yù)測
七、利用SnowNLP庫對彈幕進(jìn)行情感分析
八、誰是彈幕發(fā)射器?
????????近期,GPT-4在網(wǎng)絡(luò)上引起了軒然大波,b站上也出現(xiàn)了許許多多關(guān)于GPT-4的解說視頻,其中有一個解說視頻受到了網(wǎng)友的熱烈追捧,目前已填充有2萬多的彈幕,這也引起了本人的極大興趣,因此對該視頻的彈幕進(jìn)行了爬取,并記錄于mysql數(shù)據(jù)庫中,以進(jìn)行數(shù)據(jù)分析、數(shù)據(jù)挖掘、彈幕數(shù)量預(yù)測和情緒分類等等。話不多說,正文開始。
一、利用Python爬取彈幕
? ? ? ? 首先打開以下鏈接,該鏈接便是彈幕的視頻來源,點(diǎn)擊以下鏈接并打開,右鍵點(diǎn)擊-檢查,查看網(wǎng)頁編寫代碼,再依此點(diǎn)擊--網(wǎng)絡(luò)--Fetch-XHR,然后播放視頻,隨著視頻中彈幕的出現(xiàn),右側(cè)出現(xiàn)一次次請求,直到看到cid代號的出現(xiàn),如下圖右下角,記下cid的值,將該值填入下述網(wǎng)址中:https://comment.bilibili.com/cid值.xml,打開該網(wǎng)址就可以看到一條條彈幕信息了,我們要爬取的對象便是這條網(wǎng)址了。(爬取技術(shù)請用于正途)
【漸構(gòu)】萬字科普GPT4為何會顛覆現(xiàn)有工作流;為何你要關(guān)注微軟Copilot、文心一言等大模型_嗶哩嗶哩_bilibili
?確定了網(wǎng)址,下面開始利用python對該網(wǎng)址進(jìn)行爬取,代碼如下:
import requests from bs4 import BeautifulSoup response = requests.get("https://comment.bilibili.com/1054910356.xml") #要爬取的網(wǎng)址 response.encoding='utf8' #編碼方式 html = response.text soup = BeautifulSoup(html) #使用beautifulsoup庫快速查找我們想要的信息 all_txt = soup.findAll("d") #尋找到所有包含d的行 txt=[all_txts.attrs ["p"]for all_txts in all_txt] #尋找到所有包含d的行中屬性為p的值,這里邊包含了彈幕的虛擬id等 txtss=[all_txts.string for all_txts in all_txt] #尋找到所有包含d的行中的字符串?dāng)?shù)據(jù),即彈幕內(nèi)容 txtsss=[txts.replace(' ','') for txts in txtss] #將字符串中的空格消除掉 print(txt,txtsss) ###打印便可看見一條條彈幕的屬性和內(nèi)容了。輸出結(jié)果如下:
?二、利用幾行代碼直接生成詞云
danmustr=''.join(i for i in txtsss) #將所有彈幕拼接在一起 words=list(jieba.cut(danmustr)) ###利用jieba庫將彈幕按詞進(jìn)行切分 words=[i for i in words if len(i)>1] ###挑出長度大于1的詞語(為去除諸如?,哈,啊等字符) wc=wordcloud.WordCloud(height=1000,width=1000,font_path='simsun.ttc')#利用wordcloud庫定義詞云圖片的信息 wc.generate(' '.join(words)) ##生成圖片 print(wc) plt.imshow(wc) plt.show()執(zhí)行上述代碼,得到以下詞云圖片:
?????????分析:從該詞云圖片信息可以知道,大量彈幕中都出現(xiàn)了就是人類、ai、中國等詞眼,看來大家都認(rèn)為gpt-4是一場重大變革,ai的智能程度或可比肩人類,另外大家也在討論中國應(yīng)當(dāng)如何應(yīng)對這次ai的巨大變革。
三、將彈幕屬性和內(nèi)容放入mysql當(dāng)中
????????為便于對彈幕數(shù)據(jù)的調(diào)用和處理,我們需要將其存入mysql數(shù)據(jù)庫中,代碼如下:
import pandas as pd from datetime import datetime from sqlalchemy import create_engine,textpg=pd.DataFrame({"paragraphs": txt,"comment":txtsss})#將彈幕屬性和彈幕內(nèi)容放入dataframe中 pg["time_happen"]=pg['paragraphs'].map(lambda x:x.split(',')[0]) #將彈幕的第一個屬性值拆分為time_happen列 pg["danmu_gundong"]=pg['paragraphs'].map(lambda x:x.split(',')[1]) #將彈幕的第二個屬性值拆分為danmu_gundong列 pg["danmu_size"]=pg['paragraphs'].map(lambda x:x.split(',')[2]) #與上類似 pg["danmu_color"]=pg['paragraphs'].map(lambda x:x.split(',')[3]) #與上類似 pg["danmu_ture_time"]=pg['paragraphs'].map(lambda x:x.split(',')[4]) #與上類似 pg["danmu_mode"]=pg['paragraphs'].map(lambda x:x.split(',')[5]) #與上類似 pg["user_id"]=pg['paragraphs'].map(lambda x:x.split(',')[6]) #與上類似 pg["danmu_ture_time"]=pg['danmu_ture_time'].apply(lambda x:datetime.fromtimestamp(int(x))) #將時間戳先轉(zhuǎn)換為datetime,可不轉(zhuǎn) pg["danmu_ture_time"]=pg['danmu_ture_time'].apply(lambda x:x.date()) #將datetime轉(zhuǎn)換為date日期,可不轉(zhuǎn) engine=create_engine('mysql+pymysql://root:123456@localhost/gpt') #利用sqlalchemy庫建立mysql的引擎 pg.to_sql(name='gptlast',con=engine,index=False,if_exists='replace')#記得安裝pymysql庫!!,將數(shù)據(jù)寫入mysql執(zhí)行上述代碼,便可寫入mysql當(dāng)中,如下:
?四、分析彈幕在視頻各節(jié)點(diǎn)的數(shù)量
1、分析視頻各個片段出現(xiàn)的彈幕數(shù)量
????????本文爬取了近萬條彈幕,繪制了彈幕數(shù)量與出現(xiàn)時間的曲線圖,繪制曲線圖的代碼如下:
import matplotlib from matplotlib import pyplot as plt engine=create_engine('mysql+pymysql://root:123456@localhost/gpt') #利用sqlalchemy庫建立mysql的引擎 df=pd.read_sql(text('select * from gptlast'),con=engine.connect())#從mysql數(shù)據(jù)庫中查找出所有彈幕信息 list_time_happen=df["time_happen"].tolist() list_count_time_happen=[] for i in range(500):count_time_happen = 0for j in range(7200):if i * 6.028 <= float(list_time_happen[j]) < (i + 1) * 6.028:list_time_happen[j]=icount_time_happen +=1list_count_time_happen.append(count_time_happen) print(list_count_time_happen) matplotlib.rcParams['font.family']='SimHei' matplotlib.rcParams['font.size']=12 plt.plot(list_count_time_happen,color='g',linewidth=2,label="視頻各時段的彈幕數(shù)量") plt.xlabel("視頻的各個時段,以6.028s為一個區(qū)間") plt.ylabel('視頻各個時段的彈幕數(shù)量',labelpad=-40, #調(diào)整y軸標(biāo)簽與y軸的距離y=1.02, #調(diào)整y軸標(biāo)簽的上下位置rotation=0) plt.grid() plt.show()?繪制得到的曲線圖如下:
?????????可以看出,視頻的開頭和結(jié)尾彈幕數(shù)量較多,彈幕數(shù)量最多的時間段是視頻的48分23秒的位置,說明這個時間段的內(nèi)容廣受關(guān)注,本文查看視頻的該時間段可知,這段內(nèi)容講述了:中國已經(jīng)錯了三次工業(yè)革命,不能再錯過這次的gpt-4了,該段視頻截圖如下。
? ? ? ? 在筆者看來,這段內(nèi)容是整個視頻的重中之重,可以說是整個視頻的論點(diǎn)。因此引起了大家的廣泛關(guān)注,面對這場ai浪潮,我們到底該如何應(yīng)對?
2、分析視頻各大章節(jié)出現(xiàn)的彈幕數(shù)量
? ? ? ? 分析視頻各大章節(jié)出現(xiàn)的彈幕數(shù)量,以分析網(wǎng)友對各個章節(jié)的喜愛程度,代碼和上一小節(jié)類似,此處便不貼了。繪制直方圖和餅狀圖如下:
?
? ? ? ? ?可以看出視頻第四章節(jié):未來影響,出現(xiàn)的彈幕最多,看來網(wǎng)友對GPT-4的未來影響比較感興趣。但是,以上兩圖統(tǒng)計(jì)的是各個章節(jié)的彈幕數(shù)量,然而各個章節(jié)的時間長短不一,比如第一章引言只有幾分鐘,而其他幾章有十幾分鐘,十幾分鐘內(nèi)出現(xiàn)的彈幕數(shù)量當(dāng)然比幾分鐘內(nèi)出現(xiàn)的彈幕更多了,因此不區(qū)分章節(jié)時間長度而進(jìn)行彈幕數(shù)量比較,是不太合理的,因此本文接著統(tǒng)計(jì)了各大章節(jié)每秒出現(xiàn)的彈幕數(shù)量,得到直方圖和餅狀圖如下:
?
? ? ? ? ?從以上兩圖可以看出,第一章節(jié)開始逆襲,其每秒彈幕數(shù)量是最多的,因?yàn)槭且曨l的開頭,所以這是可以理解的,另外第三章每秒彈幕數(shù)量還是最少的,看來廣大網(wǎng)友對這個大模型如何訓(xùn)練的并不感興趣呀。
3.分析視頻各小節(jié)出現(xiàn)的彈幕數(shù)量
????????分析視頻各小節(jié)出現(xiàn)的彈幕數(shù)量,以分析網(wǎng)友對各個小節(jié)的喜愛程度,代碼和上上節(jié)類似,此處便不貼了。繪制直方圖和餅狀圖如下:
?
? ? ? ? ?可以看出,4.3、5.3及4.2小節(jié)出現(xiàn)的彈幕數(shù)量最多,4.3是gpt-4的社會影響,5.3是gpt-4對國家競爭力的影響,4.2是gpt-4的應(yīng)用價值,體現(xiàn)出了廣大網(wǎng)友憂國憂民和注重實(shí)踐應(yīng)用的共同點(diǎn)呀。
? ? ? ? 類似的,我們再來看看各小節(jié)的每秒彈幕數(shù)量,如下直方圖和餅狀圖:
?
? ? ? ? ?通過上面兩圖可以發(fā)現(xiàn),還是視頻的開頭和結(jié)尾的每秒彈幕數(shù)量比較多,另外就是2.1實(shí)質(zhì)功能小節(jié)彈幕數(shù)量也比較多,這小節(jié)介紹了gpt-4的通俗原理,也引起了廣大網(wǎng)友的積極討論。
五、分析彈幕數(shù)量和日期的關(guān)系
1、分析不同日期的彈幕數(shù)量
import time list_time_true=df["danmu_ture_time"].tolist() #將dataframe中的時間戳列轉(zhuǎn)換成列表 dt='2023-3-15 0:0:0' #彈幕最早出現(xiàn)時間 time_=time.strptime(dt,"%Y-%m-%d %H:%M:%S") #將dt轉(zhuǎn)換成strptime time_small=time.mktime(time_) #將strptime轉(zhuǎn)換成時間戳 list_count_time_happen=[] for i in range(28): #該視頻共公布28天,因此彈幕跨度為28天count_time_happen = 0 #用于記錄這28天每天的彈幕數(shù)量for j in range(7200):if i*3600*24+time_small <= int(list_time_true[j]) < (i+1)*3600*24+time_small:list_time_true[j] = i #這行代碼可有可有count_time_happen += 1 #如果是當(dāng)天的彈幕,則+1list_count_time_happen.append(count_time_happen) #將28天每天的彈幕數(shù)量記錄于該列表中 print(list_count_time_happen) matplotlib.rcParams['font.family']='SimHei' matplotlib.rcParams['font.size']=12 color=['deepskyblue','orange'] plt.bar(range(28), list_count_time_happen,color=color,width=0.4) plt.xlabel("發(fā)送彈幕的日期,從3月15開始,4月11結(jié)束") plt.ylabel('每天彈幕數(shù)量',labelpad=-40, #調(diào)整y軸標(biāo)簽與y軸的距離y=1.02, #調(diào)整y軸標(biāo)簽的上下位置rotation=0) plt.xticks([0,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],[15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,1,2,3,4,5,6,7,8,9,10,11]) plt.show()? ? ? ? 得到每天彈幕數(shù)量的直方圖如下:
?????????觀察以上直方圖我們可以發(fā)現(xiàn),彈幕數(shù)量會先增多再減少,持續(xù)波浪狀前進(jìn),視頻剛發(fā)布初期,彈幕增長的速度是最快的,后期彈幕數(shù)量雖也有增長,但是勢頭沒有前期高。另外查詢?nèi)諝v可以發(fā)現(xiàn),彈幕數(shù)量比較高的幾天,幾乎都是周末,工作日的彈幕數(shù)量較少,因此彈幕數(shù)量會出現(xiàn)波峰波谷,波浪狀前進(jìn),看來廣大網(wǎng)友工作日都在努力搬磚,沒有過多空閑時間逛b站呀。
2、上午、下午、晚上的彈幕數(shù)量
? ? ? ? 分析上午、下午和晚上的彈幕數(shù)量會不會有不同?代碼思路和上節(jié)類似,這里便不貼了,繪制的直方圖和餅狀圖如下圖:
?
???????觀察以上兩圖可知,下午和晚上的彈幕數(shù)量最多,估計(jì)大家上午的時間都非常倉促,掙扎著起床就要去工作了,上午沒有屬于自己的時間,哈哈。下午的彈幕數(shù)量最高,估計(jì)大家在午休前都會逛會b站,筆者也是如此,晚上的情況大致也類似。
3、每天不同細(xì)分時間段的彈幕數(shù)量
????????上節(jié)分析了上午、下午與晚上的彈幕數(shù)量,但是時間跨度較大,分析比較粗糙,下面針對更細(xì)分的時間段進(jìn)行彈幕數(shù)量分析。將一天分成12個時間段,分別為0時~2時,2時~4時,4時~6時......22時~24時,繪制了各個時間段的彈幕數(shù)量直方圖和餅狀圖:
?
????????分析以上兩圖可知,20時~22時、22時~24時和12時~14時的彈幕數(shù)量最多,說明廣大網(wǎng)友都是晝伏夜出的,晚上的時間比較充足,另外中午午休也可以抽出時間逛逛b站。4時~6時、6時~8時及2時~4時的彈幕數(shù)量最小,廣大網(wǎng)友應(yīng)該進(jìn)入夢鄉(xiāng)了。
六、利用LSTM網(wǎng)絡(luò)對彈幕數(shù)量進(jìn)行預(yù)測
? ? ? ? 由5.1可知,本文共收集了28天的彈幕數(shù)量,將28天的彈幕數(shù)量分為訓(xùn)練集和測試集,前22天的彈幕用作訓(xùn)練,后6天的彈幕用作測試,如下圖所示。本文以5天的彈幕數(shù)量為滑動窗口,預(yù)測下一天的彈幕數(shù)量,因此可得到訓(xùn)練集17組,測試集6組。
????????使用雙層LSTM網(wǎng)絡(luò)作為預(yù)測模型,網(wǎng)絡(luò)每層神經(jīng)元個數(shù)為6個(因?yàn)楸疚臄?shù)據(jù)集較為簡單,使用6個神經(jīng)元足以),LSTM網(wǎng)絡(luò)層后接一層全連接層。代碼如下:
####建立數(shù)據(jù)集 device=torch.device ('cuda:0' if torch.cuda.is_available() else 'cpu') count_max=max(list_count_time_happen) #歸一化 for i in range(28):list_count_time_happen[i]=list_count_time_happen[i]/count_max train_data=list_count_time_happen[0:22] test_data=list_count_time_happen[22:28] train_data_x=torch.zeros((17,5)) train_data_y=torch.zeros((17,1)) for i in range(17):train_data_x[i,0]=torch.tensor(train_data[i])train_data_x[i, 1] = torch.tensor(train_data[i+1])train_data_x[i, 2] = torch.tensor(train_data[i+2])train_data_x[i, 3] = torch.tensor(train_data[i+3])train_data_x[i, 4] = torch.tensor(train_data[i+4])train_data_y[i,:]=torch.tensor((train_data[i+5])) test_data_x=torch.zeros((6,5)) test_data_y=torch.zeros((6,1)) for i in range(6):test_data_x[i,0]=torch.tensor(list_count_time_happen[17+i])test_data_x[i, 1] =torch.tensor(list_count_time_happen[17 + i+1])test_data_x[i, 2] = torch.tensor(list_count_time_happen[17 + i+2])test_data_x[i, 3] = torch.tensor(list_count_time_happen[17 + i+3])test_data_x[i, 4] = torch.tensor(list_count_time_happen[17 + i+4])test_data_y[i,:]=torch.tensor(list_count_time_happen[17+i+5]) print(train_data_x.dtype,train_data_y.dtype,test_data_x.dtype,test_data_y.dtype) ####構(gòu)建網(wǎng)絡(luò)模型class LsTM(nn.Module):def __init__(self):super(LsTM, self).__init__()# 定義LSTMself.rnn = nn.LSTM(1, 6,2,batch_first=True)# 定義回歸層網(wǎng)絡(luò),輸入的特征維度等于LSTM的輸出,輸出維度為1)self.reg = nn.Sequential(nn.Linear(6, 1))def forward(self, x):x=x.reshape(-1,5,1)#x = x.view(x.size(0), -1)x, (ht,ct) = self.rnn(x)ht = ht.reshape(-1, 2, 6)ht=ht[:,1,:]x = F.sigmoid(self.reg(ht))return xmodel = LsTM().to(device)quanzhi_pipei=5000 criterion = nn.MSELoss() optimizer_ExpLR = torch.optim.Adam(model.parameters(), lr=0.001,betas=(0.9,0.999),eps=1e-08,weight_decay=0,amsgrad=False) epoch=0 a=3 for i in range(2000):epoch=epoch+1optimizer_ExpLR.zero_grad()outputs = model(train_data_x.cuda())target = train_data_y.cuda()loss = criterion(outputs, target)loss.backward()optimizer_ExpLR.step()with torch.no_grad():if epoch % 2 == 0:print("--------------歷經(jīng)第{}次循環(huán)------------".format(epoch))print('--------當(dāng)前的損失率等于:{}-------'.format(loss.item())) test_outputs = model(test_data_x.cuda()).cpu().detach().numpy() test_outputs=test_outputs.reshape((6,1)) ####繪制真實(shí)值與預(yù)測值的對比圖 matplotlib.rcParams['font.family']='SimHei' matplotlib.rcParams['font.size']=12 plt.plot(range(6),test_data_y,range(6),test_outputs) plt.legend(['true value','predicted value']) plt.xlabel("時間") plt.ylabel('彈幕數(shù)量占比',labelpad=-40, #調(diào)整y軸標(biāo)簽與y軸的距離y=1.02, #調(diào)整y軸標(biāo)簽的上下位置rotation=0) plt.show()得到預(yù)測值與真實(shí)值的對比圖如下:
?????????預(yù)測效果不太理想,但是這是情有可原的,因?yàn)橛?xùn)練集太小,只有17組!!!盡力了老鐵!
七、利用SnowNLP庫對彈幕進(jìn)行情感分析
????????利用snownlp庫對彈幕進(jìn)行情感分析,這個庫非常方便,直接調(diào)用其作為函數(shù)處理dataframe即可,返回對彈幕內(nèi)容的評分,評分越高越積極,所以代碼也是非常的簡潔,如下所示:
import snownlp import seaborn as sn df['sentiment']=df["comment"].apply(lambda x:snownlp.SnowNLP(x).sentiments) pd.set_option('display.max_rows', None) # 顯示所有行 # print(df[["comment",'sentiment']]) matplotlib.rcParams['font.family']='SimHei' matplotlib.rcParams['font.size']=12 matplotlib.rcParams['axes.unicode_minus']=False ax=sn.distplot(df['sentiment'],hist_kws={'color':'deepskyblue'},kde_kws={'color':'orange'},bins=20) ax.set_title("GPT-4解說視頻整體情感傾向") plt.show()利用庫seaborn可得到如下整體彈幕情緒分析圖如下:
?????????從以上情感分析圖可知,彈幕中有很多積極地彈幕,但同時,消極的彈幕也不少。進(jìn)一步的,筆者將情感評分>0.9分的彈幕選作為積極的彈幕,而情感評分<0.5的彈幕選作為消極的彈幕,如以下代碼所示:
sentiment_list=df['sentiment'].tolist() count_=[0,0] for i in range(7200):if sentiment_list[i]>=0.9:count_[0]=count_[0]+1elif sentiment_list[i]<0.5:count_[1]=count_[1]+1 matplotlib.rcParams['font.family']='SimHei' matplotlib.rcParams['font.size']=12 color=['deepskyblue','orange'] plt.bar(range(2),count_,color=color,width=0.3) plt.xlabel("情緒種類") plt.ylabel('各情緒種類的彈幕數(shù)量',labelpad=-40, #調(diào)整y軸標(biāo)簽與y軸的距離y=1.02, #調(diào)整y軸標(biāo)簽的上下位置rotation=0) plt.xticks(range(2),['積極','消極']) plt.show()繪制得到積極彈幕數(shù)量和消極彈幕數(shù)量對比圖如下:
? ? ? ? ?可以發(fā)現(xiàn),消極的彈幕比積極地彈幕更多,部分原因是國內(nèi)難以使用gpt-4,這引起了部分網(wǎng)友的怨言。
八、誰是彈幕發(fā)射器?
? ? ? ? 本節(jié)統(tǒng)計(jì)了這近萬條彈幕的虛擬id,得到了所有不同用戶發(fā)送的彈幕數(shù)量,如下圖所示:
?????????觀察上圖可知,第1名用戶發(fā)送了35條彈幕,第2名用戶發(fā)送了大概30條,依此遞減,大部分用戶都只發(fā)送了一條彈幕,大致是從第1200名用戶開始,至第4800名用戶,這三千多用戶都只發(fā)送了一條彈幕。發(fā)送了35條彈幕的這位用戶的彈幕內(nèi)容,多為對未來的思考和擔(dān)憂,可見這位用戶對中國未來充滿信心,又覺得中國的路還很長,足見其憂國憂民的形象。
????????以上便是本條博客的全部內(nèi)容了,完結(jié),撒花~感謝觀看
總結(jié)
以上是生活随笔為你收集整理的利用python对b站某GPT-4解说视频的近万条弹幕进行爬取、数据挖掘、数据分析、弹幕数量预测及情绪分类的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android快速SDK(12)文本pd
- 下一篇: vue实现icon刷新动画