跳到主要內容

Python 網絡爬蟲實戰:爬取 B站《全職高手》20萬條評論數據


本周我們的目標是:B站(嗶哩嗶哩彈幕網 https://www.bilibili.com )視頻評論數據。



我們都知道,B站有很多號稱"鎮站之寶"的視頻,擁有着數量極其恐怖的評論和彈幕。所以這次我們的目標就是,爬取B站視頻的評論數據,分析其為何會深受大家喜愛。


首先去調研一下,B站評論數量最多的視頻是哪一個。。。好在已經有大佬已經統計過了,我們來看一哈!


​【B站大數據可視化】B站評論數最多的視頻究竟是?來自 <https://www.bilibili.com/video/av34900167/>

 


嗯?《全職高手》,有點意思,第一集和最後一集分別佔據了評論數量排行榜的第二名和第一名,遠超了其他很多很火的番。那好,就拿它下手吧,看看它到底強在哪兒。


廢話不多說,先去B站看看這部神劇到底有多好看 https://www.bilibili.com/bangumi/play/ep107656



額,需要開通大會員才能觀看。。。


好吧,不看就不看,不過好在雖然視頻看不了,評論卻是可以看的。



感受到它的恐怖了嗎?63w6條的評論!9千多頁!果然是不同凡響啊。


接下來,我們就開始編寫爬蟲,爬取這些數據吧。


 


使用爬蟲爬取網頁一般分為四個階段:分析目標網頁,獲取網頁內容,提取關鍵信息,輸出保存。


1. 分析目標網頁



  • 首先觀察評論區結構,發現評論區為鼠標點擊翻頁形式,共 9399 頁,每一頁有 20 條評論,每條評論中包含 用戶名、評論內容、評論樓層、時間日期、點贊數等信息展示。





  • 接着我們按 F12 召喚出開發者工具,切換到Network。然後用鼠標點擊評論翻頁,觀察這個過程有什麼變化,並以此來制定我們的爬取策略。


  • 我們不難發現,整個過程中 URL 不變,說明評論區翻頁不是通過 URL 控制。而在每翻一頁的時候,網頁會向服務器發出這樣的請求(請看 Request URL)。





  • 點擊 Preview 欄,可以切換到預覽頁面,也就是說,可以看到這個請求返回的結果是什麼。下面是該請求返回的 json 文件,包含了在 replies 里包含了本頁的評論數據。在這個 json 文件里,我們可以發現,這裏面包含了太多的信息,除了網頁上展示的信息,還有很多沒展示出來的信息也有,簡直是挖到寶了。不過,我們這裏用不到,通通忽略掉,只挑我們關注的部分就好了。




2. 獲取網頁內容


網頁內容分析完畢,可以正式寫代碼爬了。


 1 import requests
2
3 def fetchURL(url):
4 '''
5 功能:訪問 url 的網頁,獲取網頁內容並返回
6 參數:
7 url :目標網頁的 url
8 返回:目標網頁的 html 內容
9 '''
10 headers = {
11 'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
12 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36',
13 }
14
15 try:
16 r = requests.get(url,headers=headers)
17 r.raise_for_status()
18 print(r.url)
19 return r.text
20 except requests.HTTPError as e:
21 print(e)
22 print("HTTPError")
23 except requests.RequestException as e:
24 print(e)
25 except:
26 print("Unknown Error !")
27
28
29 if __name__ == '__main__':
30 url = 'https://api.bilibili.com/x/v2/reply?callback=jQuery172020326544171595695_1541502273311&jsonp=jsonp&pn=2&type=1&oid=11357166&sort=0&_=1541502312050'
31 html = fetchURL(url)
32 print(html)


不過,在運行過後,你會發現,403 錯誤,服務器拒絕了我們的訪問。


運行結果:


403 Client Error: Forbidden for url: https://api.bilibili.com/x/v2/reply?callback=jQuery172020326544171595695_1541502273311&jsonp=jsonp&pn=2&type=1&oid=11357166&sort=0&_=1541502312050
HTTPError
None


同樣的,這個請求放瀏覽器地址欄裏面直接打開,會變403,什麼也訪問不到。



這是我們本次爬蟲遇到的第一個坑。在瀏覽器中能正常返迴響應,但是直接打開請求鏈接時,卻會被服務器拒絕。(我第一反應是 cookie ,將瀏覽器中的 cookie 放入爬蟲的請求頭中,重新訪問,發現沒用),或許這也算是一個小的反爬蟲機制吧。


網上查閱資料之後,我找到了解決的方法(雖然不了解原理),原請求的 URL 參數如下:


callback = jQuery1720913511919053787_1541340948898
jsonp
= jsonp
pn
= 2
type
= 1
oid
= 11357166&sort=0
_
= 1541341035236


其中,真正有用的參數只有三個:pn(頁數),type(=1)和oid(視頻id)。刪除其餘不必要的參數之後,用新整理出的url去訪問,成功獲取到評論數據。



https://api.bilibili.com/x/v2/reply?type=1&oid=11357166&pn=2





然後,在主函數中,通過寫一個 for 循環,通過改變 pn 的值,獲取每一頁的評論數據。


1 if __name__ == '__main__':
2 for page in range(0,9400):
3 url = 'https://api.bilibili.com/x/v2/reply?type=1&oid=11357166&pn=' + str(page)
4 html = fetchURL(url)

 


3. 提取關鍵信息


通過 json 庫對獲取到的響應內容進行解析,然後提取我們需要的內容:樓層,用戶名,性別,時間,評價,點贊數,回複數。


 1 import json
2 import time
3
4 def parserHtml(html):
5 '''
6 功能:根據參數 html 給定的內存型 HTML 文件,嘗試解析其結構,獲取所需內容
7 參數:
8 html:類似文件的內存 HTML 文本對象
9 '''
10 s = json.loads(html)
11
12 for i in range(20):
13 comment = s['data']['replies'][i]
14
15 # 樓層,用戶名,性別,時間,評價,點贊數,回複數
16 floor = comment['floor']
17 username = comment['member']['uname']
18 sex = comment['member']['sex']
19 ctime = time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(comment['ctime']))
20 content = comment['content']['message']
21 likes = comment['like']
22 rcounts = comment['rcount']
23
24 print('--'+str(floor) + ':' + username + '('+sex+')' + ':'+ctime)
25 print(content)
26 print('like : '+ str(likes) + ' ' + 'replies : ' + str(rcounts))
27 print(' ')

部分運行結果如下:

--204187:day可可鈴(保密):2018-11-05 18:16:22
太太又出本了,這次真的木錢了(´;ω;`)
like :
1 replies : 0

--204186:長夜未央233(女):2018-11-05 16:24:52
12區打卡
like :
2 replies : 0

--204185:果然還是人渣一枚(男):2018-11-05 13:48:09
貌似忘來了好幾天
like :
1 replies : 1

--204183:day可可鈴(保密):2018-11-05 13:12:38
要準備去學校了,萬惡的期中考試( ´_ゝ`)
like :
2 replies : 0

--204182:拾秋以恭弘=叶 恭弘(保密):2018-11-05 12:04:19
11月5日打卡( ̄▽ ̄)
like :
1 replies : 0

--204181:芝米士噠(女):2018-11-05 07:53:43
這次是真的錯過了一個億[蛆音娘_扶額]
like :
2 replies : 1

 

4. 保存輸出


我們把這些數據以 csv 的格式保存於本地,即完成了本次爬蟲的全部任務。下面附上爬蟲的全部代碼。


  1 import requests
2 import json
3 import time
4
5 def fetchURL(url):
6 '''
7 功能:訪問 url 的網頁,獲取網頁內容並返回
8 參數:
9 url :目標網頁的 url
10 返回:目標網頁的 html 內容
11 '''
12 headers = {
13 'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
14 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36',
15 }
16
17 try:
18 r = requests.get(url,headers=headers)
19 r.raise_for_status()
20 print(r.url)
21 return r.text
22 except requests.HTTPError as e:
23 print(e)
24 print("HTTPError")
25 except requests.RequestException as e:
26 print(e)
27 except:
28 print("Unknown Error !")
29
30
31 def parserHtml(html):
32 '''
33 功能:根據參數 html 給定的內存型 HTML 文件,嘗試解析其結構,獲取所需內容
34 參數:
35 html:類似文件的內存 HTML 文本對象
36 '''
37 try:
38 s = json.loads(html)
39 except:
40 print('error')
41
42 commentlist = []
43 hlist = []
44
45 hlist.append("序號")
46 hlist.append("名字")
47 hlist.append("性別")
48 hlist.append("時間")
49 hlist.append("評論")
50 hlist.append("點贊數")
51 hlist.append("回複數")
52
53 #commentlist.append(hlist)
54
55 # 樓層,用戶名,性別,時間,評價,點贊數,回複數
56 for i in range(20):
57 comment = s['data']['replies'][i]
58 blist = []
59
60 floor = comment['floor']
61 username = comment['member']['uname']
62 sex = comment['member']['sex']
63 ctime = time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(comment['ctime']))
64 content = comment['content']['message']
65 likes = comment['like']
66 rcounts = comment['rcount']
67
68 blist.append(floor)
69 blist.append(username)
70 blist.append(sex)
71 blist.append(ctime)
72 blist.append(content)
73 blist.append(likes)
74 blist.append(rcounts)
75
76 commentlist.append(blist)
77
78 writePage(commentlist)
79 print('---'*20)
80
81 def writePage(urating):
82 '''
83 Function : To write the content of html into a local file
84 html : The response content
85 filename : the local filename to be used stored the response
86 '''
87
88 import pandas as pd
89 dataframe = pd.DataFrame(urating)
90 dataframe.to_csv('Bilibili_comment5-1000條.csv', mode='a', index=False, sep=',', header=False)
91
92
93 if __name__ == '__main__':
94 for page in range(0,9400):
95 url = 'https://api.bilibili.com/x/v2/reply?type=1&oid=11357166&pn=' + str(page)
96 html = fetchURL(url)
97 parserHtml(html)
98
99 # 為了降低被封ip的風險,每爬20頁便歇5秒。
100 if page%20 == 0:
101 time.sleep(5)

 


寫在最後


在爬取過程中,還是遇到了很多的小坑的。


1. 請求的 url 不能直接用,需要對參數進行篩選整理后才能訪問。


2. 爬取過程其實並不順利,因為如果爬取期間如果有用戶發表評論,則請求返回的響應會為空導致程序出錯。所以在實際爬取過程中,記錄爬取的位置,以便出錯之後從該位置繼續爬。(並且,挑選深夜一兩點這種發帖人數少的時間段,可以極大程度的減少程序出錯的機率)


3. 爬取到的數據有多處不一致,其實這個不算是坑,不過這裏還是講一下,免得產生困惑。


        a. 就是評論區樓層只到了20多萬,但是評論數量卻有63萬多條,這個不一致主要是由於B站的評論是可以回復的,回復的評論也會計算到總評論數里。我們這裏只爬樓層的評論,而評論的回復則忽略,只統計回複數即可。


        b. 評論區樓層在20萬條左右,但是我們最後爬取下來的數據只有18萬條左右,反覆檢查爬蟲程序及原網站后發現,這個屬於正常現象,因為有刪評論的情況,評論刪除之後,後面的樓層並不會重新排序,而是就這樣把刪掉的那層空下了。導致樓層數和評論數不一致。


 


 


 如果文章中有哪裡沒有講明白,或者講解有誤的地方,歡迎在評論區批評指正,或者掃描下面的二維碼,加我微信,大家一起學習交流,共同進步。



 

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】



※教你寫出一流的銷售文案?



※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益



※回頭車貨運收費標準



※別再煩惱如何寫文案,掌握八大原則!



※超省錢租車方案



※產品缺大量曝光嗎?你需要的是一流包裝設計!



Orignal From: Python 網絡爬蟲實戰:爬取 B站《全職高手》20萬條評論數據

留言

這個網誌中的熱門文章

架構設計 | 異步處理流程,多種實現模式詳解

本文源碼:GitHub·點這裏 || GitEE·點這裏 一、異步處理 1、異步概念 異步處理不用阻塞當前線程來等待處理完成,而是允許後續操作,直至其它線程將處理完成,並回調通知此線程。 必須強調一個基礎邏輯,異步是一種設計理念,異步操作不等於多線程,MQ中間件,或者消息廣播,這些是可以實現異步處理的方式。 同步處理和異步處理相對,需要實時處理並響應,一旦超過時間會結束會話,在該過程中調用方一直在等待響應方處理完成並返回。同步類似電話溝通,需要實時對話,異步則類似短信交流,發送消息之後無需保持等待狀態。 2、異步處理優點 雖然異步處理不能實時響應,但是處理複雜業務場景,多數情況都會使用異步處理。 異步可以解耦業務間的流程關聯,降低耦合度; 降低接口響應時間,例如用戶註冊,異步生成相關信息表; 異步可以提高系統性能,提升吞吐量; 流量削峰即把請求先承接下來,然後在異步處理; 異步用在不同服務間,可以隔離服務,避免雪崩; 異步處理的實現方式有很多種,常見多線程,消息中間件,發布訂閱的廣播模式,其根據邏輯在於先把請求承接下來,放入容器中,在從容器中把請求取出,統一調度處理。 注意 :一定要監控任務是否產生積壓過度情況,任務如果積壓到雪崩之勢的地步,你會感覺每一片雪花都想勇闖天涯。 3、異步處理模式 異步流程處理的實現有好多方式,但是實際開發中常用的就那麼幾種,例如: 基於接口異步響應,常用在第三方對接流程; 基於消息生產和消費模式,解耦複雜流程; 基於發布和訂閱的廣播模式,常見系統通知 異步適用的業務場景,對數據強一致性的要求不高,異步處理的數據更多時候追求的是最終一致性。 二、接口響應異步 1、流程描述 基於接口異步響應的方式,有一個本地業務服務,第三方接口服務,流程如下: 本地服務發起請求,調用第三方服務接口; 請求包含業務參數,和成功或失敗的回調地址; 第三方服務實時響應流水號,作為該調用的標識; 之後第三方服務處理請求,得到最終處理結果; 如果處理成功,回調本地服務的成功通知接口; 如果處理失敗,回調本地服務的失敗通知接口; 整個流程基於部分異步和部分實時的模式,完整處理; 注意 :如...

.NET Core前後端分離快速開發框架(Core.3.0+AntdVue)

.NET Core前後端分離快速開發框架(Core.3.0+AntdVue) 目錄 引言 時間真快,轉眼今年又要過去了。回想今年,依次開源發布了 Colder.Fx.Net.AdminLTE(254Star) 、 Colder.Fx.Core.AdminLTE(335Star) 、 DotNettySocket(82Star) 、 IdHelper(47Star) ,這些框架及組件都是本着以實際出發,實事求是的態度,力求提高開發效率(我自己都是第一個使用者),目前來看反響不錯。但是隨着前端和後端技術的不斷變革,尤其是前端,目前大環境已經是前後端完全分離為主的開發模式,在這樣的大環境和必然趨勢之下,傳統的MVC就顯得有些落伍了。在這樣的背景下,一款前後端分離的.NET開發框架就顯得尤為必要,由此便定了框架的升級目標: 前後端分離 。 首先後端技術的選擇,從目前的數據來看,.NET Core的發展遠遠快於.NET Framework,最簡單的分析就是Colder.Fx.Core.AdminLTE發布比Colder.Fx.Net.AdminLTE晚,但是星星卻後來居上而且比前者多30%,並且這個差距在不斷擴大,由點及面的分析可以看出我們廣大.NET開發人員學習的熱情和积極向上的態度,並不是某些人所認為的那麼不堪( 走自己的路,讓別人說去吧 )。大環境上微軟积極擁抱開源,大力發展.NET Core, 可以說前途一片光明。因此後端決定採用 .NET Core3.0 ,不再浪費精力去支持.NET Framework。 然後是前端技術選擇,首選是三大js框架選擇,也是從實際出發,Vue相對其它而言更加容易上手,並且功能也毫不遜色,深得各種大小公司喜歡,如果偏要說缺點的話,那就是對TS支持不行,但是即將發布Vue3.0肯定會改變這一缺陷。選擇了Vue之後,然後就是UI框架的選擇了,這裏的選擇更多了,我選擇了Ant Design Vue,理由便是簡潔方便,十分符合我的設計理念。 技術選型完畢之後便...

台北市住宅、社區建創儲能設備 最高可獲600萬元補助

為了推廣分散式發電,台北市環保局預計補助1億元供住宅社區設置創能、儲能設備,計有3種方案可供選擇。環保局說明,每案補助額度不超過建制總經費49%,社區每案最高可獲200萬至600萬元補助,住宅每案補助上限100萬元,5月1日起開放申請。 環保局說明,台北市溫室氣體排放量7成以上來自住商部門,其中以使用電力造成間接溫室氣體排放為大宗,台北市平均年用電量約159.86億度,1度電約等同排放0.5公斤二氧化碳,若想達成2050年淨零排放目標,僅靠節能減碳無法達成,必須發展綠色創能、儲能,並且參考歐洲、日本的做法,採分散式發電方式,推廣到社區、住家、商辦,達到供電自給自足目標。 因此,環保局推出「台北市住宅社區創能儲能及節能補助計畫」,補助對象為台北市轄內房屋所有權人及社區管理委員會,補助方案共計3種,每一申請人或每一場址僅能獲1次補助,每案補助額度不超過建置總經費49%為限,5月1日到7月31日開放申請,但補助經費用完即停止申請。 環保局說明,方案A補助對象以社區為主,公共區域申請創能儲能及節能項目,每案補助上限新台幣600萬元;方案B分為住宅或社區公共區域申請創能搭配儲能項目(創能或儲能方案不得單獨申請),社區每案補助上限新台幣400萬元,住宅每案補助上限100萬元。方案C補助對象也是社區,公共區域申請節能項目,每案補助上限新台幣200萬元。 網頁設計 最專業,超強功能平台可客製,窩窩以「數位行銷」「品牌經營」「網站與應用程式」「印刷品設計」等四大主軸,為每一位客戶客製建立行銷脈絡及洞燭市場先機,請問 台中電動車 哪裡在賣比較便宜可以到台中景泰電動車門市去看看總店:臺中市潭子區潭秀里雅潭路一段102-1號。 電動車補助 推薦評價好的 iphone維修 中心擁有專業的維修技術團隊,同時聘請資深iphone手機維修專家,現場說明手機問題,快速修理,沒修好不收錢住家的頂樓裝 太陽光電 聽說可發揮隔熱功效一線推薦東陽能源擁有核心技術、產品研發、系統規劃設置、專業團隊的太陽能發電廠商。 網頁設計 一頭霧水該從何著手呢? 回頭車 貨運收費標準宇安交通關係企業,自成立迄今,即秉持著「以誠待人」、「以實處事」的企業信念 台中搬家公司 教你幾個打包小技巧,輕鬆整理裝箱!還在煩惱搬家費用要多少哪?台中大展搬家線上試算搬家費用,從此不再擔心「物品怎麼計費」、「多...