利用python对b站某GPT-4解说视频的近万条弹幕进行爬取、数据挖掘、数据分析、弹幕数量预测及情绪分类
????????
目錄
一、利用Python爬取彈幕
?二、利用幾行代碼直接生成詞云
三、將彈幕屬性和內容放入mysql當中
?四、分析彈幕在視頻各節點的數量
1、分析視頻各個片段出現的彈幕數量
2、分析視頻各大章節出現的彈幕數量
3.分析視頻各小節出現的彈幕數量
五、分析彈幕數量和日期的關系
1、分析不同日期的彈幕數量
2、上午、下午、晚上的彈幕數量
3、每天不同細分時間段的彈幕數量
六、利用LSTM網絡對彈幕數量進行預測
七、利用SnowNLP庫對彈幕進行情感分析
八、誰是彈幕發射器?
????????近期,GPT-4在網絡上引起了軒然大波,b站上也出現了許許多多關于GPT-4的解說視頻,其中有一個解說視頻受到了網友的熱烈追捧,目前已填充有2萬多的彈幕,這也引起了本人的極大興趣,因此對該視頻的彈幕進行了爬取,并記錄于mysql數據庫中,以進行數據分析、數據挖掘、彈幕數量預測和情緒分類等等。話不多說,正文開始。
一、利用Python爬取彈幕
? ? ? ? 首先打開以下鏈接,該鏈接便是彈幕的視頻來源,點擊以下鏈接并打開,右鍵點擊-檢查,查看網頁編寫代碼,再依此點擊--網絡--Fetch-XHR,然后播放視頻,隨著視頻中彈幕的出現,右側出現一次次請求,直到看到cid代號的出現,如下圖右下角,記下cid的值,將該值填入下述網址中:https://comment.bilibili.com/cid值.xml,打開該網址就可以看到一條條彈幕信息了,我們要爬取的對象便是這條網址了。(爬取技術請用于正途)
【漸構】萬字科普GPT4為何會顛覆現有工作流;為何你要關注微軟Copilot、文心一言等大模型_嗶哩嗶哩_bilibili
?確定了網址,下面開始利用python對該網址進行爬取,代碼如下:
import requests from bs4 import BeautifulSoup response = requests.get("https://comment.bilibili.com/1054910356.xml") #要爬取的網址 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的行中的字符串數據,即彈幕內容 txtsss=[txts.replace(' ','') for txts in txtss] #將字符串中的空格消除掉 print(txt,txtsss) ###打印便可看見一條條彈幕的屬性和內容了。輸出結果如下:
?二、利用幾行代碼直接生成詞云
danmustr=''.join(i for i in txtsss) #將所有彈幕拼接在一起 words=list(jieba.cut(danmustr)) ###利用jieba庫將彈幕按詞進行切分 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()執行上述代碼,得到以下詞云圖片:
?????????分析:從該詞云圖片信息可以知道,大量彈幕中都出現了就是人類、ai、中國等詞眼,看來大家都認為gpt-4是一場重大變革,ai的智能程度或可比肩人類,另外大家也在討論中國應當如何應對這次ai的巨大變革。
三、將彈幕屬性和內容放入mysql當中
????????為便于對彈幕數據的調用和處理,我們需要將其存入mysql數據庫中,代碼如下:
import pandas as pd from datetime import datetime from sqlalchemy import create_engine,textpg=pd.DataFrame({"paragraphs": txt,"comment":txtsss})#將彈幕屬性和彈幕內容放入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))) #將時間戳先轉換為datetime,可不轉 pg["danmu_ture_time"]=pg['danmu_ture_time'].apply(lambda x:x.date()) #將datetime轉換為date日期,可不轉 engine=create_engine('mysql+pymysql://root:123456@localhost/gpt') #利用sqlalchemy庫建立mysql的引擎 pg.to_sql(name='gptlast',con=engine,index=False,if_exists='replace')#記得安裝pymysql庫!!,將數據寫入mysql執行上述代碼,便可寫入mysql當中,如下:
?四、分析彈幕在視頻各節點的數量
1、分析視頻各個片段出現的彈幕數量
????????本文爬取了近萬條彈幕,繪制了彈幕數量與出現時間的曲線圖,繪制曲線圖的代碼如下:
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數據庫中查找出所有彈幕信息 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="視頻各時段的彈幕數量") plt.xlabel("視頻的各個時段,以6.028s為一個區間") plt.ylabel('視頻各個時段的彈幕數量',labelpad=-40, #調整y軸標簽與y軸的距離y=1.02, #調整y軸標簽的上下位置rotation=0) plt.grid() plt.show()?繪制得到的曲線圖如下:
?????????可以看出,視頻的開頭和結尾彈幕數量較多,彈幕數量最多的時間段是視頻的48分23秒的位置,說明這個時間段的內容廣受關注,本文查看視頻的該時間段可知,這段內容講述了:中國已經錯了三次工業革命,不能再錯過這次的gpt-4了,該段視頻截圖如下。
? ? ? ? 在筆者看來,這段內容是整個視頻的重中之重,可以說是整個視頻的論點。因此引起了大家的廣泛關注,面對這場ai浪潮,我們到底該如何應對?
2、分析視頻各大章節出現的彈幕數量
? ? ? ? 分析視頻各大章節出現的彈幕數量,以分析網友對各個章節的喜愛程度,代碼和上一小節類似,此處便不貼了。繪制直方圖和餅狀圖如下:
?
? ? ? ? ?可以看出視頻第四章節:未來影響,出現的彈幕最多,看來網友對GPT-4的未來影響比較感興趣。但是,以上兩圖統計的是各個章節的彈幕數量,然而各個章節的時間長短不一,比如第一章引言只有幾分鐘,而其他幾章有十幾分鐘,十幾分鐘內出現的彈幕數量當然比幾分鐘內出現的彈幕更多了,因此不區分章節時間長度而進行彈幕數量比較,是不太合理的,因此本文接著統計了各大章節每秒出現的彈幕數量,得到直方圖和餅狀圖如下:
?
? ? ? ? ?從以上兩圖可以看出,第一章節開始逆襲,其每秒彈幕數量是最多的,因為是視頻的開頭,所以這是可以理解的,另外第三章每秒彈幕數量還是最少的,看來廣大網友對這個大模型如何訓練的并不感興趣呀。
3.分析視頻各小節出現的彈幕數量
????????分析視頻各小節出現的彈幕數量,以分析網友對各個小節的喜愛程度,代碼和上上節類似,此處便不貼了。繪制直方圖和餅狀圖如下:
?
? ? ? ? ?可以看出,4.3、5.3及4.2小節出現的彈幕數量最多,4.3是gpt-4的社會影響,5.3是gpt-4對國家競爭力的影響,4.2是gpt-4的應用價值,體現出了廣大網友憂國憂民和注重實踐應用的共同點呀。
? ? ? ? 類似的,我們再來看看各小節的每秒彈幕數量,如下直方圖和餅狀圖:
?
? ? ? ? ?通過上面兩圖可以發現,還是視頻的開頭和結尾的每秒彈幕數量比較多,另外就是2.1實質功能小節彈幕數量也比較多,這小節介紹了gpt-4的通俗原理,也引起了廣大網友的積極討論。
五、分析彈幕數量和日期的關系
1、分析不同日期的彈幕數量
import time list_time_true=df["danmu_ture_time"].tolist() #將dataframe中的時間戳列轉換成列表 dt='2023-3-15 0:0:0' #彈幕最早出現時間 time_=time.strptime(dt,"%Y-%m-%d %H:%M:%S") #將dt轉換成strptime time_small=time.mktime(time_) #將strptime轉換成時間戳 list_count_time_happen=[] for i in range(28): #該視頻共公布28天,因此彈幕跨度為28天count_time_happen = 0 #用于記錄這28天每天的彈幕數量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 #如果是當天的彈幕,則+1list_count_time_happen.append(count_time_happen) #將28天每天的彈幕數量記錄于該列表中 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("發送彈幕的日期,從3月15開始,4月11結束") plt.ylabel('每天彈幕數量',labelpad=-40, #調整y軸標簽與y軸的距離y=1.02, #調整y軸標簽的上下位置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()? ? ? ? 得到每天彈幕數量的直方圖如下:
?????????觀察以上直方圖我們可以發現,彈幕數量會先增多再減少,持續波浪狀前進,視頻剛發布初期,彈幕增長的速度是最快的,后期彈幕數量雖也有增長,但是勢頭沒有前期高。另外查詢日歷可以發現,彈幕數量比較高的幾天,幾乎都是周末,工作日的彈幕數量較少,因此彈幕數量會出現波峰波谷,波浪狀前進,看來廣大網友工作日都在努力搬磚,沒有過多空閑時間逛b站呀。
2、上午、下午、晚上的彈幕數量
? ? ? ? 分析上午、下午和晚上的彈幕數量會不會有不同?代碼思路和上節類似,這里便不貼了,繪制的直方圖和餅狀圖如下圖:
?
???????觀察以上兩圖可知,下午和晚上的彈幕數量最多,估計大家上午的時間都非常倉促,掙扎著起床就要去工作了,上午沒有屬于自己的時間,哈哈。下午的彈幕數量最高,估計大家在午休前都會逛會b站,筆者也是如此,晚上的情況大致也類似。
3、每天不同細分時間段的彈幕數量
????????上節分析了上午、下午與晚上的彈幕數量,但是時間跨度較大,分析比較粗糙,下面針對更細分的時間段進行彈幕數量分析。將一天分成12個時間段,分別為0時~2時,2時~4時,4時~6時......22時~24時,繪制了各個時間段的彈幕數量直方圖和餅狀圖:
?
????????分析以上兩圖可知,20時~22時、22時~24時和12時~14時的彈幕數量最多,說明廣大網友都是晝伏夜出的,晚上的時間比較充足,另外中午午休也可以抽出時間逛逛b站。4時~6時、6時~8時及2時~4時的彈幕數量最小,廣大網友應該進入夢鄉了。
六、利用LSTM網絡對彈幕數量進行預測
? ? ? ? 由5.1可知,本文共收集了28天的彈幕數量,將28天的彈幕數量分為訓練集和測試集,前22天的彈幕用作訓練,后6天的彈幕用作測試,如下圖所示。本文以5天的彈幕數量為滑動窗口,預測下一天的彈幕數量,因此可得到訓練集17組,測試集6組。
????????使用雙層LSTM網絡作為預測模型,網絡每層神經元個數為6個(因為本文數據集較為簡單,使用6個神經元足以),LSTM網絡層后接一層全連接層。代碼如下:
####建立數據集 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) ####構建網絡模型class LsTM(nn.Module):def __init__(self):super(LsTM, self).__init__()# 定義LSTMself.rnn = nn.LSTM(1, 6,2,batch_first=True)# 定義回歸層網絡,輸入的特征維度等于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("--------------歷經第{}次循環------------".format(epoch))print('--------當前的損失率等于:{}-------'.format(loss.item())) test_outputs = model(test_data_x.cuda()).cpu().detach().numpy() test_outputs=test_outputs.reshape((6,1)) ####繪制真實值與預測值的對比圖 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('彈幕數量占比',labelpad=-40, #調整y軸標簽與y軸的距離y=1.02, #調整y軸標簽的上下位置rotation=0) plt.show()得到預測值與真實值的對比圖如下:
?????????預測效果不太理想,但是這是情有可原的,因為訓練集太小,只有17組!!!盡力了老鐵!
七、利用SnowNLP庫對彈幕進行情感分析
????????利用snownlp庫對彈幕進行情感分析,這個庫非常方便,直接調用其作為函數處理dataframe即可,返回對彈幕內容的評分,評分越高越積極,所以代碼也是非常的簡潔,如下所示:
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可得到如下整體彈幕情緒分析圖如下:
?????????從以上情感分析圖可知,彈幕中有很多積極地彈幕,但同時,消極的彈幕也不少。進一步的,筆者將情感評分>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('各情緒種類的彈幕數量',labelpad=-40, #調整y軸標簽與y軸的距離y=1.02, #調整y軸標簽的上下位置rotation=0) plt.xticks(range(2),['積極','消極']) plt.show()繪制得到積極彈幕數量和消極彈幕數量對比圖如下:
? ? ? ? ?可以發現,消極的彈幕比積極地彈幕更多,部分原因是國內難以使用gpt-4,這引起了部分網友的怨言。
八、誰是彈幕發射器?
? ? ? ? 本節統計了這近萬條彈幕的虛擬id,得到了所有不同用戶發送的彈幕數量,如下圖所示:
?????????觀察上圖可知,第1名用戶發送了35條彈幕,第2名用戶發送了大概30條,依此遞減,大部分用戶都只發送了一條彈幕,大致是從第1200名用戶開始,至第4800名用戶,這三千多用戶都只發送了一條彈幕。發送了35條彈幕的這位用戶的彈幕內容,多為對未來的思考和擔憂,可見這位用戶對中國未來充滿信心,又覺得中國的路還很長,足見其憂國憂民的形象。
????????以上便是本條博客的全部內容了,完結,撒花~感謝觀看
總結
以上是生活随笔為你收集整理的利用python对b站某GPT-4解说视频的近万条弹幕进行爬取、数据挖掘、数据分析、弹幕数量预测及情绪分类的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android快速SDK(12)文本pd
- 下一篇: 通过Python实现对xls表格按类别统