Python網絡爬蟲--爬取bilibili排行榜


一、選題的背景

 

為什么要選擇此選題?要達到的數據分析的預期目標是什么?(10 分)

現在大家都很喜歡b站,我也作為b站老用戶,所以這個爬蟲通過爬取b站播放排行榜信息,來看看最近必看的有用的好玩的任何視頻。

二、主題式網絡爬蟲設計方案(10 分)

1.主題式網絡爬蟲名稱:爬取b站熱門播放排行榜

2.主題式網絡爬蟲爬取的內容與數據特征分析:

通過request爬取b站熱門視頻排行榜的排名、播放量、彈幕數

使用BeautifulSoup分析網頁結構定位內容所在標簽獲取數據

使用Numpy對獲取的數據進行數據清洗

使用matplotlib對數據進行可視化處理

 

 

3.主題式網絡爬蟲設計方案概述:

 

數據獲取需要分為幾個步驟實現:

 

1) 通過request獲取網頁資源

 

2) 使用BuautifulSoup解析網頁,定位爬取資源

 

3) 編寫代碼將數據保存到csv文件中

 

三、主題頁面的結構特征分析(10 分)

 

數據來源:

 

https://www.bilibili.com/v/popular/all?spm_id_from=333.851.b_7072696d61727950616765546162.3

 

 

Htmls頁面解析

 

(1) 需要爬取的網頁

 

(1) 按下F12打開開發者模式

 

 

(1) 按下ctrl + shift + c然后點擊需要爬取的內容

 

 

 

(1) 從最下面的層級列表中可以看到我們需要爬取的標題最終在a.title這個標簽下面

 

 

 

(5) 同理找到播放量和彈幕數

 

 

 

 

 

四、網絡爬蟲程序設計

1.

數據爬取及采集:

---------------------------------------------------------------------------------------------

導入程序所需要的所有第三方運行庫

 

復制代碼
 1 import requests #獲取頁面數據
 2 import pandas as pd #用於數據清洗
 3 from bs4 import BeautifulSoup #解析頁面
 4 import numpy as np
 5 import matplotlib #繪圖庫
 6 import seaborn as sns
 7 from matplotlib import pyplot as plt
 8 import re #用於正則表達式
 9 from scipy.sparse import data
10 import matplotlib.pyplot as plt
11 from imageio import imread
12 from wordcloud import WordCloud
復制代碼

獲取頁面響應數據

復制代碼
 1 #獲取頁面響應數據
 2 
 3 def  getHtmlText(url):
 4     try:
 5         #UA偽裝
 6         headers = {
 7             'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 Edg/96.0.1054.62'
 8         }
 9         html = page_text = requests.get(url = url,headers = headers)
10         # html.encoding = 'utf-8' #設置頁面編碼格式為utf-8防止獲取到的是亂碼
11         htmlText = html.text
12         # print(htmlText)
13         return htmlText
14     except:
15         print("獲取頁面數據失敗") #若出現異常打印字符串
復制代碼

BeautifulSoup進行頁面解析

1 #使用BeautifulSoup進行頁面解析
2 def ymjiexi(html_text):
3     soup = BeautifulSoup(html_text,'html.parser')
4     return soup

 

 

對爬取內容進行定位

復制代碼
 1 #對爬取內容進行定位
 2 def  Title(): #獲取標題並進行存儲
 3     tit = [] #創建數組進行存儲
 4     title = ymjiexi(getHtmlText(url)).select('.info > a')
 5     for ti in title:
 6         tit.append(ti.text)
 7     return tit
 8 #獲取播放量並進行存儲
 9 def getBo():
10     bofan = [] #創建數組進行存儲
11     bo = ymjiexi(getHtmlText(url)).select('.detail-state > span:nth-of-type(1)')
12     for b in bo:
13         bof = re.findall(r'\d+\.\d+|\d+',b.text)
14         bofan.append(bof[0])
15     return bofan
復制代碼

 

 

 

 

 

獲取彈幕並進行存儲

 

復制代碼
 1 #獲取彈幕並進行存儲
 2 def  danmu():
 3     danmus = [] #存儲彈幕數
 4     danmu = ymjiexi(getHtmlText(url)).select('.detail-state > span:nth-of-type(2)')
 5     for d in danmu:
 6         bof = re.findall('\d+\.\d+|\d+',d.text)
 7         if float(bof[0]) < 10: 
 8            bof[0] = float(bof[0]) * 10000 #如果彈幕數量
 9         danmus.append(bof[0])
10     return danmus 
復制代碼

運行得到結果

復制代碼
 1 if __name__ == '__main__':
 2     url = 'https://www.bilibili.com/v/popular/rank/all'
 3     ymjiexi(getHtmlText(url))
 4     Title() #獲取標題
 5     getBo() #獲取播放量
 6     danmu() #獲取彈幕量
 7     datas = [] #存儲標題和播放量
 8     print("{:^10}\t{:^30}\t{:^40}\t{:^30}".format( '排名','標題', '播放量','彈幕數'))
 9     for i in range(10):
10         print("{:^10}\t{:^30}\t{:^40}\t{:^30}".format(i+1,Title()[i],getBo()[i],danmu()[i]))
11         datas.append([i+1,Title()[i],getBo()[i],danmu()[i]])


12 對數據進行清理: 13 14 15 df = pd.DataFrame(pd.read_csv('b站播放量排行榜.csv')) #導入文件 16 #查找重復值 17 df.duplicated() 18 print(df.duplicated()) 19 刪除無效行列 20 21 # 刪除無效列 22 23 df.drop('標題',axis = 1,inplace = True) 24 25 print(df.head(10)) 26 27 # 查找是否有空值 28 29 print(df['播放量'].isnull().value_counts()) 30 31 print(df['彈幕數'].isnull().value_counts()) 32 33 34 35 異常值的觀察 36 37 38 39 abnormal = df.describe() 40 41 42 43 print(abnormal) 44 45 # 查看相關系數 46 47 xishu = df.corr() 48 49 print(xishu)
復制代碼

數據分析與可視化:

散點圖

復制代碼
 1 def  aScatter():
 2     plt.rcParams['font.sans-serif'] = ['SimHei']  # 顯示中文標簽,防止數據可視化總出現中文字符不顯示
 3     x = df.播放量
 4     y = df.彈幕數
 5     plt.xlabel('播放量')
 6     plt.ylabel('彈幕數')
 7     plt.scatter(x, y, color = "red", label = "點", s = 50)
 8     plt.title("播放量與彈幕數量的散點圖")
 9     plt.legend(loc = 'best')
10     plt.show()
11 aScatter()
復制代碼

 

 

 

折線圖

復制代碼
 1 #  折線圖
 2 #     排名與彈幕數的折線圖
 3 def  brokenLine():
 4     plt.rcParams['font.sans-serif'] = ['SimHei']  # 顯示中文標簽,防止數據可視化總出現中文字符不顯示
 5     dp = pd.DataFrame(pd.read_csv('b站播放量排行榜.csv'))
 6     x = dp.排名
 7     y = dp.彈幕數
 8     plt.xlabel("排名")
 9     plt.ylabel("彈幕數")
10     plt.plot(x, y, color = "green", label = "折線")
11     plt.title("播放量與彈幕數的折線圖")
12     plt.legend()
13     plt.show()
14 brokenLine()
復制代碼

 

 

 

扇形圖

復制代碼
 1 #播放量與彈幕數的扇形圖
 2 def  pieChart():
 3     dp = pd.DataFrame(pd.read_csv('b站播放量排行榜(刪除后).csv'))
 4     plt.rcParams['font.sans-serif'] = ['SimHei']  # 顯示中文標簽,防止數據可視化總出現中文字符不顯示
 5     x = df.播放量
 6     y = df.彈幕數
 7     name = [x[0], x[1], x[2], x[3], x[4]]
 8     math = [y[0], y[1], y[2], y[3], y[4]]
 9     explode = [0.1, 0.1, 0.1, 0.1, 0.1]
10     plt.pie(math, labels = name, colors = ["r", "g", "c", "b", "y"], explode = explode)
11     plt.axis("equal")
12     plt.title("b站熱榜播放量與彈幕數的扇形圖")
13     plt.show()
14 pieChart()
復制代碼

 

 

回歸直線圖

復制代碼
 1  def  back():
 2     dp = pd.DataFrame(pd.read_csv('b站播放量排行榜.csv'))
 3     plt.rcParams['font.sans-serif'] = ['SimHei']  # 顯示中文標簽,防止數據可視化總出現中文字符不顯示
 4     plt.rcParams['font.serif'] = ['KaiTi']
 5     plt.rcParams['axes.unicode_minus'] = False
 6     x = df.排名
 7     y = df.彈幕數
 8     # X,Y為散點圖的
 9     X = df.排名
10     Y = df.彈幕數
11     # 先定義所需要的數據
12     x_i2 = 0
13     x_i = 0
14     y_i = 0
15     # 用mean()方法計算出x,y的均值
16     q = x.mean()
17     w = y.mean()
18     for i in range(7):
19         x_i2 = x_i + x[i] * x[i]
20         x_i = x_i + x[i]
21         y_i = y_i + y[i]
22     m_1 = x_i * y_i - 7 * q * w
23     m_2 = x_i2 - 7 * q * q
24     k = m_1 / m_2
25     # 截距
26     b = w - q * k
27     x = np.linspace(0, 7)
28     y = k * x + b
29     print("斜率k=", k, "截距b=", b)
30     plt.figure(figsize = (6, 4))
31     plt.xlabel('排名')
32     plt.ylabel('彈幕數')
33     plt.scatter(X, Y, color = "green", label = "散點", linewidth = 2)
34     plt.plot(x, y, color = "blue", label = "回歸直線")
35     plt.title("回歸直線圖")
36     plt.legend()
37     plt.show()
38 back()
復制代碼

 

 

條形圖

復制代碼
 1 #  繪制條形圖
 2 def  bar():
 3     plt.rcParams['font.sans-serif'] = ['SimHei']  # 顯示中文標簽,防止數據可視化總出現中文字符不顯示
 4     df = pd.DataFrame(pd.read_csv('b站播放量排行榜.csv'))
 5     x = df.排名
 6     y = df.播放量
 7     plt.xlabel('排名')
 8     plt.ylabel('播放量')
 9     plt.bar(x,y,color='red',width = 0.8)
10     plt.title("排名與播放量的條形圖")
11     plt.show()
12 bar()
復制代碼

 

 

 

 

線性關系圖

復制代碼
1 #  線性關系圖
2 def line():
3     plt.rcParams['font.sans-serif'] = ['SimHei']  # 顯示中文標簽,防止數據可視化總出現中文字符不顯示
4     plt.rcParams['font.serif'] = ['KaiTi']
5     plt.rcParams['axes.unicode_minus'] = False
6     df = pd.DataFrame(pd.read_csv('b站播放量排行榜.csv'))
7     sns.lmplot(x = "排名", y = "播放量", data = df)
8     plt.show()
9 line()
復制代碼

 

 

標題詞雲圖

復制代碼
 1 #讀取b站播放量排行榜.csv將其中的標題名稱寫到txt文本中
 2 text = pd.read_csv("b站播放量排行榜.csv", encoding='utf-8')
 3 with open("標題.txt",'a+', encoding='utf-8') as f:
 4     for title in text.標題:
 5         f.write((str(title)+'\n'))
 6 #讀取文本
 7 text=open('標題.txt',encoding='utf-8').read()
 8 #詞雲的背景圖片
 9 photo=imread('小雞.jpg')
10 Cyun=WordCloud(
11     background_color = "white",
12  mask = photo,
13 
14     width=1000,
15 
16     repeat=True,
17 
18     font_path=r'simfang.ttf',
19 
20     height=1600).generate(text)
21 
22 plt.imshow(Cyun)
23 
24 plt.axis("off")
25 
26 plt.show()
27 
28 #保存圖片
29 
30 Cyun.to_file("標題詞雲.jpg")
復制代碼

 

 爬蟲源碼:

復制代碼
  1 #導入程序所需要的所有第三方運行庫
  2 import requests
  3 import bs4
  4 import pandas as pd
  5 from bs4 import BeautifulSoup
  6 import numpy as np
  7 import matplotlib
  8 import seaborn as sns
  9 from matplotlib import pyplot as plt
 10 import re
 11 from scipy.sparse import data
 12 from wordcloud import WordCloud
 13 import matplotlib.pyplot as plt
 14 from imageio import imread
 15 
 16 
 17 plt.rcParams['font.sans-serif'] = ['SimHei']  # 顯示中文標簽,防止畫圖出現中文字符不顯示
 18 plt.rcParams['font.serif'] = ['KaiTi']
 19 plt.rcParams['axes.unicode_minus'] = False
 20 
 21 
 22 
 23 
 24 #獲取頁面數據
 25 def getHtmlText(url):
 26     try:
 27         #UA偽裝
 28         headers = {
 29             'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 Edg/96.0.1054.62'
 30         }
 31         html = page_text = requests.get(url = url,headers = headers)
 32         # html.encoding = 'utf-8' #設置頁面編碼格式為utf-8防止獲取到的是亂碼
 33         htmlText = html.text
 34         # print(htmlText)
 35         return htmlText
 36     except:
 37         print("獲取頁面數據失敗") #若出現異常打印字符串
 38 
 39 #使用BeautifulSoup進行頁面解析
 40 def ymjiexi(html_text):
 41     soup = BeautifulSoup(html_text,'html.parser')
 42     return soup
 43 
 44 #對爬取內容進行定位
 45 def Title(): #獲取標題並進行存儲
 46     tit = [] #創建數組進行存儲
 47     title = ymjiexi(getHtmlText(url)).select('.info > a')
 48     for ti in title:
 49         tit.append(ti.text)
 50     return tit
 51 #獲取播放量並進行存儲
 52 def getBo():
 53     bofan = [] #創建數組進行存儲
 54     bo = ymjiexi(getHtmlText(url)).select('.detail-state > span:nth-of-type(1)')
 55     for b in bo:
 56         bof = re.findall(r'\d+\.\d+|\d+',b.text)
 57         bofan.append(bof[0])
 58     return bofan
 59 def danmu():
 60     danmus = [] #存儲彈幕數
 61     danmu = ymjiexi(getHtmlText(url)).select('.detail-state > span:nth-of-type(2)')
 62 
 63     for d in danmu:
 64         bof = re.findall('\d+\.\d+|\d+',d.text)
 65         # print(bof)
 66         danmus.append(bof[0])
 67     return danmus
 68 
 69 
 70 if __name__ == '__main__':
 71     url = 'https://www.bilibili.com/v/popular/rank/all'
 72     ymjiexi(getHtmlText(url))
 73     Title() #獲取標題
 74     getBo() #獲取播放量
 75     danmu() #獲取彈幕量
 76     datas = [] #存儲標題和播放量
 77     print("{:^30}\t{:^40}\t{:^30}".format( '標題', '播放量','彈幕數'))
 78     for i in range(10):
 79         print("{:^30}\t{:^40}\t{:^30}".format(Title()[i],getBo()[i],danmu()[i]))
 80         datas.append([Title()[i],getBo()[i],danmu()[i]])
 81     print(datas)
 82 
 83     #將爬取到的內容保存到csv文件里進存儲和后續的數據清洗
 84     df = pd.DataFrame(datas, columns = ["標題", '播放量', '彈幕數'])
 85     df.to_csv('b站播放量排行榜.csv', index = False) #設置index = Flase防止出現未命名的列
 86     print("爬取完畢!")
 87 
 88     #進行數據清洗
 89 
 90     df = pd.DataFrame(pd.read_csv('b站播放量排行榜.csv')) #導入文件
 91     # 查找重復值
 92     df.duplicated()
 93     print(df.duplicated())
 94 
 95     # 刪除無效行
 96     df.drop('標題',axis = 1,inplace = True)
 97 
 98     print(df.head(10))
 99 
100     # 查找是否有空值
101     print(df['標題'].isnull().value_counts())
102     print(df['熱度'].isnull().value_counts())
103 
104     # 刪除彈幕數量小於20的標題
105     def drop():
106         drop = df.drop(index=(df.loc[(df['彈幕數']<20)].index))
107         print(drop)
108         drop.to_csv('b站播放量排行榜(刪除后).csv', index = False)
109         print("保存成功")
110     drop()
111 
112 
113 
114     # 異常值的觀察
115     abnormal = df.describe()
116     print(abnormal)
117 
118 
119     # 查看相關系數
120     xishu = df.corr()
121     print(xishu)
122 
123     # 散點圖
124     def aScatter():
125         x = df.播放量
126         y = df.彈幕數
127         plt.xlabel('播放量')
128         plt.ylabel('彈幕數')
129         plt.scatter(x, y, color = "red", label = "點", s = 50)
130         plt.title("播放量與彈幕數量的散點圖")
131         plt.legend(loc = 'best')
132         plt.show()
133     aScatter()
134 
135 
136     # 折線圖
137     # 播放量與彈幕數的折線圖
138     def brokenLine():
139         dp = pd.DataFrame(pd.read_csv('b站播放量排行榜(刪除后).csv'))
140         print(df.head(10))
141         x = dp.播放量
142         y = dp.彈幕數
143         plt.xlabel("播放量")
144         plt.ylabel("彈幕數")
145         plt.plot(x, y, color = "green", label = "折線")
146         plt.title("播放量與彈幕數的折線圖")
147         plt.legend()
148         plt.show()
149     brokenLine()
150 
151 
152     #播放量與彈幕數的扇形圖
153     def pieChart():
154         dp = pd.DataFrame(pd.read_csv('b站播放量排行榜(刪除后).csv'))
155         x = df.播放量
156         y = df.彈幕數
157         name = [x[0], x[1], x[2], x[3], x[4]]
158         math = [y[0], y[1], y[2], y[3], y[4]]
159         explode = [0.1, 0.1, 0.1, 0.1, 0.1]
160         plt.pie(math, labels = name, colors = ["r", "g", "c", "b", "y"], explode = explode)
161         plt.axis("equal")
162         plt.title("b站熱榜播放量與彈幕數的扇形圖")
163         plt.show()
164     pieChart()
165 
166     #播放量與彈幕數的回歸直線圖
167     # 回歸直線的圖
168     def back():
169         dp = pd.DataFrame(pd.read_csv('b站播放量排行榜(刪除后).csv'))
170 
171         x = df.播放量
172         y = df.彈幕數
173         # X,Y為散點圖的
174         X = df.播放量
175         Y = df.彈幕數
176         # 先定義所需要的數據
177         x_i2 = 0
178         x_i = 0
179         y_i = 0
180         # 用mean()方法計算出x,y的均值
181         q = x.mean()
182         w = y.mean()
183         for i in range(7):
184             x_i2 = x_i + x[i] * x[i]
185             x_i = x_i + x[i]
186             y_i = y_i + y[i]
187 
188         m_1 = x_i * y_i - 7 * q * w
189 
190         m_2 = x_i2 - 7 * q * q
191 
192         k = m_1 / m_2
193         # 截距
194         b = w - q * k
195         x = np.linspace(0, 7)
196         y = k * x + b
197         print("斜率k=", k, "截距b=", b)
198         plt.figure(figsize = (6, 4))
199         plt.xlabel('播放量')
200         plt.ylabel('彈幕數')
201         plt.scatter(X, Y, color = "green", label = "散點", linewidth = 2)
202         plt.plot(x, y, color = "blue", label = "回歸直線")
203         plt.title("回歸直線圖")
204         plt.legend()
205         plt.show()
206     back()
207 
208     #繪制條形圖
209     def bar():
210         df = pd.DataFrame(pd.read_csv('b站播放量排行榜.csv'))
211         x = df.播放量
212         y = df.彈幕數
213         plt.xlabel('播放量')
214         plt.ylabel('彈幕數')
215         plt.bar(x,y,color='red')
216         plt.title("播放量與彈幕數的條形圖")
217         plt.show()
218     bar()
219 
220 
221     # 線性關系圖
222     def line():
223         df = pd.DataFrame(pd.read_csv('b站播放量排行榜.csv'))
224         sns.lmplot(x = "播放量", y = "彈幕數", data = df)
225         plt.show()
226     line()
227 
228     #讀取b站播放量排行榜.csv將其中的標題名稱寫到txt文本中
229     text = pd.read_csv("b站播放量排行榜.csv", encoding='utf-8')
230     with open("標題.txt",'a+', encoding='utf-8') as f:
231         for title in text.標題:
232             f.write((str(title)+'\n'))
233 
234     #讀取文本
235     text=open('標題.txt',encoding='utf-8').read()
236     #詞雲的背景圖片
237     photo=imread('小雞.jpg')
238     Cyun=WordCloud(
239         background_color = "white",
240         mask = photo,
241         width=1000,
242         repeat=True,
243         font_path=r'simfang.ttf',
244         height=1600).generate(text)
245     plt.imshow(Cyun)
246     plt.axis("off")
247     plt.show()
248     #保存圖片
249     Cyun.to_file("標題詞雲.jpg")
復制代碼

總結:

經過爬蟲和數據可視化,我們可以觀察到b站排行榜的想知道的信息,雖然實用性不高,但是就是好玩,每個人所追求的東西都不一樣,爬蟲也並不只是為了完成任務型的工作,我們在學習的過程中應該真正做到學以致用,在玩中學,在學習中自己找樂子,才能找到枯燥學習中的樂趣,看看詞雲圖,是不是很喜感。當然這個也不是完全沒用的,b站確實是能夠了解很多趨於年輕態的信息,大齡人若想了解年輕人所想,不妨也試試去b站。未來我希望能繼續完善能力,在此之上有更大發展。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM