爬取bilibili綜合熱門排行榜及數據分析
一、 選題背景
根據2019年第44次《中國互聯網絡發展狀況統計報告》顯示,至2019年6月,我國網民規模為8.54億,Z世代(10-29歲)網民占比41.5%,約為3. 55億人。B站在Z世代中的人口滲透率約為12.8%,滲透率將持續提高,增長潛力巨大。在QuestMobile統計的Z世代偏愛APP榜單中,B站獨占鰲頭。Z世代是生長於移動互聯網的一代,恰逢經濟騰飛、消費升級,而且經濟水平和消費意識都較前代更強,且Z世代大多還未負擔起沉重的現實與家庭壓力,付費能力和付費意願較高,版權意識較上代人顯著提升。隨着Z世代收入和消費能力的不斷增強,中國泛娛樂市場發展前景十分光明。因此通過爬取b站近期熱門排行榜得到的數據通過可視化分析可以了解人們的喜好,更方便的定位人們的需求。
二、主題式網絡爬蟲設計方案
1.主題式網絡爬蟲名稱:
爬取bilibili綜合熱門排行榜及數據分析
2.主題式網絡爬蟲爬取的內容
爬取近期熱門視頻的標題,up主,播放數,評論數。
3.主題式網絡爬蟲設計方案概述
通過頁面使用開發者工具找到network中的XHR通過查看Headers了解網頁的請求方式,並且獲取URL。爬取數據之后,通過執行dict=json.loads(text)操作,把數據轉化為字典方便數據提取。通過執行
print(dict)的操作找到所需要爬取的內容,並且將其保存csv文件中。進行數據可視化分析。
三、主題頁面的結構特征分析
1.主題頁面的結構與特征分析
從所需爬取的頁面中 , 通過頁面使用開發者工具(F12)找到network中的XHR通過查看Headers了解網頁的請求方式,並且獲取URL(https://api.bilibili.com/x/web-interface/popular?ps=20&pn=1)
json數據結構
所需要爬取的數據都存放在這個接口里面。
2.頁面解析
通過對比參數發現只有'pn'這個參數不同,刷新頁面滑到視頻的底部,發現'pn'值為11。pn代表頁數,所以熱門視頻共有十一頁。下一步開始爬蟲。
用json方法把request返回的格式轉譯為字典,通過執行dict=json.loads(text)操作,這樣更方便數據提取。通過執行 print(dict)的操作找到所需要爬取的內容。
(PS:因為動態加載的原因,爬取的內容可能和之后的可視化有點差異,但不影響結果的展示)
3.節點(標簽)查找方法與遍歷方法
用json方法把request返回的格式轉譯為字典,從上圖輸出結果可是看出數據是來自data,list,遍歷字典for i in dict['data']['list']:。然后執行print(i)找到這些所需要的key值。后遍歷這些key值。
四、網絡爬蟲程序設計
爬蟲程序主體要包括以下各部分。
1.數據爬取與采集
1 #導入所需要的庫 2 import requests 3 import json 4 import csv 5 #爬蟲部分 6 #1.數據是動態加載的,所以需要尋找數據地址 7 def Get_data(): 8 #處理一個小小的反爬,偽裝成瀏覽器發送請求。 9 header={ 10 'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36' 11 } 12 url='https://api.bilibili.com/x/web-interface/popular' 13 #從頁面分析知道熱門數據共有11頁 14 for i in range(1,12): 15 #把URL的參數封裝成一個字典 16 param={ 17 'ps': 20, 18 'pn': i 19 } 20 res=requests.get(url=url,headers=header,params=param) 21 print(res.text) 22 #Parse(res.text)#下一步需要利用的函數 23 res.close()#關閉對網頁的爬取 24 25 if __name__ == '__main__': 26 Get_data()
爬取成功結果截圖如下:
2.提取所需的數據,並存儲
1 #2.對爬取到的數據進行解析,獲取每一條視頻數據的標題,Up主,播放量,評論數 2 3 #對所有視頻的數據都解析,每一條數據以元組的形式保存在列表中 4 all_data=[] 5 def Parse(text): 6 dict=json.loads(text)#把數據轉化為字典方便數據提取 7 # print(dict['data']['list']) 8 9 for i in dict['data']['list']: 10 # print(i['title'])#標題 11 # print(i['owner']['name'])#up主 12 # print(i['stat']['view'])#播放量 13 # print(i['stat']['danmaku'])#評論數 14 15 temp=(i['title'],i['owner']['name'],i['stat']['view'],i['stat']['danmaku']) 16 all_data.append(temp) 17 18 #3.對數據進行保存 19 def Save_data(all_data): 20 with open(r'all_data.csv',mode='w',encoding='utf-8') as fp: 21 writer=csv.writer(fp)#創建一個csv的寫對象 22 writer.writerow(['視頻名稱','up主','播放量','評論數'])#寫一行數據作為數據頭部 23 for i in all_data: 24 writer.writerow(i)#把all_data的數據寫進去 25 26 27 if __name__ == '__main__': 28 Get_data() 29 #print(all_data) 30 Save_data(all_data=all_data) 31
提取數據截圖如下圖:
生成的csv如下圖:
3.數據清洗
獲取的數據較完整,沒有出現重復和空行情況。故不需要數據清洗。
4.繪制頻率直方圖
1 import pandas as pd 2 import matplotlib.pyplot as plt 3 import numpy as np 4 import matplotlib 5 import seaborn as sns 6 from sklearn import datasets 7 from sklearn.linear_model import LinearRegression 8 from sklearn.datasets import load_boston 9 import jieba 10 from pylab import * 11 from wordcloud import WordCloud 12 13 14 #評論數的頻率直方圖 15 %matplotlib inline 16 plt.rcParams['font.sans-serif'] = ['SimHei'] 17 plt.rcParams['axes.unicode_minus'] = False 18 df=pd.read_csv('C:/Users/10365/Desktop/python期末作業/all_data.csv') 19 plt.figure 20 21 sns.distplot(df['評論數'].values,hist=True, kde=True,axlabel='tip',rug=False,fit=None,hist_kws = {'color':'b','label':'評論數'}, kde_kws={'color':'b'}) 22 plt.title("評論數的頻率直方圖",fontsize=16) 23 plt.legend() 24 plt.xlabel('評論數') 25 plt.ylabel('頻率') 26 plt.grid() 27 28 29 30 #播放量的頻率直方圖 31 sns.distplot(df['播放量'].values,hist=True, kde=True,axlabel='tip',rug=False,fit=None,hist_kws = {'color':'b','label':'播放量'}, kde_kws={'color':'b'}) 32 plt.title("播放量的頻率直方圖",fontsize=16) 33 plt.legend() 34 plt.ylabel('') 35 plt.grid()
5.繪制柱形圖
1 #TOP35的UP主與播放量的柱形圖 2 data=np.array(df['播放量'][0:35]) 3 index=np.array(df['up主'][0:35]) 4 print(data) 5 print(index) 6 plt.ylabel('播放量(百萬)') 7 8 plt.title("TOP35的UP主與播放量的柱形圖",fontsize=16) 9 s = pd.Series(data, index) 10 11 s.plot(kind='bar') 12 plt.savefig('TOP35的UP主與播放量的柱形圖.jpg') 13 14 15 16 17 #TOP35的UP主與評論數的柱形圖 18 data=np.array(df['評論數'][0:35]) 19 index=np.array(df['up主'][0:35]) 20 print(data) 21 print(index) 22 plt.ylabel('評論數') 23 24 s = pd.Series(data, index) 25 26 plt.title("TOP35的UP主與評論數的柱形圖",fontsize=16) 27 28 s.plot(kind='bar') 29 30 #數據持久化 31 plt.savefig('TOP35UP主與評論數的柱形圖.jpg')
6.繪制散點圖
1 #播放量與評論數關系的散點圖 2 x=df['播放量'].values 3 4 y=df['評論數'].values 5 6 plt.figure 7 8 size=120 9 10 plt.xlabel('播放量(百萬)') 11 12 plt.ylabel('評論數') 13 plt.scatter(x/1,y,size,color='g',label='播放評論關系') 14 plt.legend(loc=2) 15 plt.grid() 16 plt.title("播放量與評論數關系的散點圖",fontsize=16) 17 plt.show()
7.數據分析,回歸方程
1 #計算回歸方程系數和回歸方程截距 2 predict_model = LinearRegression() 3 predict_model.fit(x.reshape(-1, 1),y) 4 np.set_printoptions(precision = 3, suppress = True) 5 print("回歸方程系數{}".format(predict_model.coef_)) 6 print("回歸方程截距{0:2f}".format(predict_model.intercept_)) 7 8 9 10 #播放評論關系回歸方程圖 11 plt.scatter(x,y,size,color='g',label='播放評論關系') 12 yfit = [809.206980 + 0.002 * xi for xi in x] 13 plt.plot(x, yfit, color="r") 14 plt.ylabel('評論數') 15 plt.xlabel('播放量(百萬)') 16 plt.show()
8.繪制詞雲
1 import jieba 2 from pylab import * 3 from wordcloud import WordCloud 4 text = ' ' 5 a='' 6 df=pd.read_csv('C:/Users/10365/Desktop/python期末作業/all_data.csv') 7 for line in df['視頻名稱']: 8 a+= line 9 text+=a 10 # 使用jieba模塊將字符串分割為單詞列表 11 cut_text = ' '.join(jieba.cut(text)) 12 color_mask = imread('C:/Users/10365/Desktop/python期末作業/python截圖圖片/書本.jpg') #設置背景圖 13 cloud = WordCloud( 14 background_color = 'white', 15 # 對中文操作必須指明字體 16 font_path='C:/Windows/Fonts/優設標題黑_貓啃網.ttf', 17 mask = color_mask, 18 max_words = 50, 19 max_font_size = 200 20 ).generate(cut_text) 21 22 # 保存詞雲圖片 23 cloud.to_file('ciwordcloud.jpg') 24 plt.imshow(cloud) 25 plt.axis('off') 26 plt.show()
9.數據持久化
生成CSV文件
將數據可視化的圖片保存成jpg的形式
通過 #例如 plt.savefig('詞雲.jpg') 實現數據可視化
10.完整代碼
1 #導入所需要的庫 2 import requests 3 import json 4 import csv 5 6 #爬蟲部分 7 #1.數據是動態加載的,所以需要尋找數據地址 8 def Get_data(): 9 header={ 10 'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36' 11 } 12 url='https://api.bilibili.com/x/web-interface/popular' 13 for i in range(1,12): 14 param={ 15 'ps': 20, 16 'pn': i 17 } 18 res=requests.get(url=url,headers=header,params=param) 19 #print(res.text) 20 Parse(res.text) 21 res.close() 22 23 #2.對爬取到的數據進行解析,獲取每一條視頻數據的標題,Up主,播放量,評論數 24 25 #對所有視頻的數據都解析,每一條數據以元組的形式保存在列表中 26 all_data=[] 27 def Parse(text): 28 dict=json.loads(text)#把數據轉化為字典方便數據提取 29 # print(dict['data']['list']) 30 31 for i in dict['data']['list']: 32 # print(i['title'])#標題 33 # print(i['owner']['name'])#up主 34 # print(i['stat']['view'])#播放量 35 # print(i['stat']['danmaku'])#評論數 36 37 temp=(i['title'],i['owner']['name'],i['stat']['view'],i['stat']['danmaku']) 38 all_data.append(temp) 39 40 #3.對數據進行保存 41 42 def Save_data(all_data): 43 with open(r'all_data.csv',mode='w',encoding='utf-8') as fp: 44 writer=csv.writer(fp)#創建一個csv的寫對象 45 writer.writerow(['視頻名稱','up主','播放量','評論數'])#寫一行數據作為數據頭部 46 for i in all_data: 47 writer.writerow(i)#把all_data的數據寫進去 48 49 50 51 if __name__ == '__main__': 52 Get_data() 53 #print(all_data) 54 Save_data(all_data=all_data) 55 56 57 58 #數據可視化部分 59 60 import pandas as pd 61 62 import matplotlib.pyplot as plt 63 64 import numpy as np 65 66 import matplotlib 67 68 import seaborn as sns 69 70 71 #評論數的頻率直方圖 72 73 %matplotlib inline 74 plt.rcParams['font.sans-serif'] = ['SimHei'] 75 plt.rcParams['axes.unicode_minus'] = False 76 df=pd.read_csv('C:/Users/10365/Desktop/python期末作業/all_data.csv') 77 plt.figure 78 79 sns.distplot(df['評論數'].values,hist=True, kde=True,axlabel='tip', 80 rug=False,fit=None,hist_kws = {'color':'b','label':'評論數'}, 81 kde_kws={'color':'b'}) 82 83 plt.legend() 84 plt.xlabel('評論數') 85 plt.ylabel('頻率') 86 plt.grid() 87 88 89 90 #播放量的頻率直方圖 91 92 sns.distplot(df['播放量'].values,hist=True, kde=True,axlabel='tip',rug=False, 93 fit=None,hist_kws = {'color':'b','label':'播放量'}, 94 kde_kws={'color':'b'}) 95 96 plt.legend() 97 98 plt.ylabel('') 99 100 plt.grid() 101 102 103 104 #播放量與評論數關系的散點圖 105 106 x=df['播放量'].values 107 108 y=df['評論數'].values 109 110 plt.figure 111 112 size=120 113 114 plt.xlabel('播放量(百萬)') 115 116 plt.ylabel('評論數') 117 plt.scatter(x/1,y,size,color='g',label='播放評論關系') 118 119 plt.legend(loc=2) 120 plt.title("播放量與評論數關系的散點圖",fontsize=16) 121 plt.grid() 122 123 plt.show() 124 125 126 #TOP35的UP主與播放量的柱形圖 127 128 data=np.array(df['播放量'][0:35]) 129 index=np.array(df['up主'][0:35]) 130 print(data) 131 print(index) 132 plt.ylabel('播放量(百萬)') 133 134 plt.title("TOP35的UP主與播放量的柱形圖",fontsize=16) 135 s = pd.Series(data, index) 136 137 s.plot(kind='bar') 138 plt.savefig('TOP35的UP主與播放量的柱形圖.jpg') 139 140 141 142 #TOP35的UP主與評論數的柱形圖 143 144 data=np.array(df['評論數'][0:35]) 145 index=np.array(df['up主'][0:35]) 146 print(data) 147 print(index) 148 plt.ylabel('評論數') 149 150 s = pd.Series(data, index) 151 152 plt.title("TOP35的UP主與評論數的柱形圖",fontsize=16) 153 154 s.plot(kind='bar') 155 156 #數據持久化 157 plt.savefig('TOP35UP主與評論數的柱形圖.jpg') 158 159 160 161 #數據分析,回歸方程 162 163 from sklearn import datasets 164 165 from sklearn.linear_model import LinearRegression 166 167 from sklearn.datasets import load_boston 168 169 import pandas as pd 170 171 172 #計算回歸方程系數和回歸方程截距 173 174 predict_model = LinearRegression() 175 predict_model.fit(x.reshape(-1, 1),y) 176 np.set_printoptions(precision = 3, suppress = True) 177 print("回歸方程系數{}".format(predict_model.coef_)) 178 print("回歸方程截距{0:2f}".format(predict_model.intercept_)) 179 180 181 #播放評論關系回歸方程圖 182 183 plt.scatter(x,y,size,color='g',label='播放評論關系') 184 yfit = [809.206980 + 0.002 * xi for xi in x] 185 plt.plot(x, yfit, color="r") 186 187 plt.ylabel('評論數') 188 189 plt.xlabel('播放量(百萬)') 190 191 plt.title("播放評論關系回歸方程圖",fontsize=16) 192 193 plt.show() 194 195 plt.savefig('播放評論關系回歸方程圖.jpg') 196 197 198 199 #繪制詞雲,查看出現最多的詞語 200 201 import jieba 202 from pylab import * 203 from wordcloud import WordCloud 204 text = ' ' 205 a='' 206 df=pd.read_csv('C:/Users/10365/Desktop/python期末作業/all_data.csv') 207 for line in df['視頻名稱']: 208 a+= line 209 text+=a 210 211 # 使用jieba模塊將字符串分割為單詞列表 212 cut_text = ' '.join(jieba.cut(text)) 213 #設置背景圖 214 color_mask = imread('C:/Users/10365/Desktop/python期末作業/python截圖圖片/書本.jpg') 215 216 cloud = WordCloud( 217 218 background_color = 'white', 219 # 對中文操作必須指明字體 220 font_path='C:/Windows/Fonts/優設標題黑_貓啃網.ttf', 221 mask = color_mask, 222 max_words = 50, 223 max_font_size = 200 224 ).generate(cut_text) 225 226 # 保存詞雲圖片 227 cloud.to_file('ciwordcloud.jpg') 228 plt.imshow(cloud) 229 plt.axis('off') 230 plt.show()
五、總結
1.經過對主題數據的分析與可視化,可以得到哪些結論?是否達到預期的目標?
結論: (1)通過近期熱門視頻排行榜數據爬取得知播放量最高的up主是龍饃饃,說明人們對這類視頻的關注度高
(2)通過近期熱門視頻排行榜數據爬取並結合詞雲得知評論數最高的是原神官方賬號,說明人們對該視頻的討論激烈。
因為缺少分區等方面的信息,不能更高效的分析出哪類視頻在受眾方面的情況,不能清楚分析出這些列別視頻的受歡迎程度。
2.在完成此設計過程中,得到哪些收獲?以及要改進的建議?
通過爬取bilibili近期熱門排行榜,在項目代碼編寫階段鞏固了基礎知識,並且通過網上的視頻了解到對爬取頁面和解析頁面的多種方法,如(requests模塊,bs4,json等)所以爬蟲方面進展還是比較順利的。但是由於基礎的原因在數據可視化的實現中還是比較吃力的,參考了很多種實現方法。數據可視化這方面進展比較緩慢拉下完成項目的進度。
日后要加強對繪圖庫的理解與使用,通過各種實戰來熟練。