Python網路爬蟲實戰:爬取知乎話題下 18934 條回答資料
好久沒有更爬蟲了,因為馬上要畢業了,最近在準備畢設的專案,沒時間搞這個了,不好意西了大家。
事情是這樣的,上週末,我一單身單身單身的好哥兒們找我,拜託我個事兒。。。我這個單身單身單身的好哥們喜歡逛知乎,尤其喜歡看一些情感型別的話題,寄希望於這個來解決單身的煩惱。某天,他看到了知乎上這樣一個問題:
你的擇偶標準是怎樣的?
這個問題下的回答數竟有有一萬八千多條,然後這傢伙忍不住了,來找我幫忙,看能不能用爬蟲爬一下,看看到底都是些什麼人在評論,回答的人裡面到底是小哥哥們多還是小姐姐們多呢?
單身單身單身的好哥們求助,肯定要幫嘛是吧!畢設先放一邊也要幫嘛!
所以我們這次來爬知乎!
一、首先明確需求,爬什麼資料?
通過一番交流,最終我們確認要爬的資料是:知乎網站上 “你的擇偶標準是怎樣的?”問題下回答的使用者的資料,包括
- 使用者的 ID
- 使用者的暱稱
- 使用者的性別
- 使用者回答的贊同數
- 使用者回答的評論數
經過初步檢視,這些資訊在不登陸的情況下,在網頁中都可以檢視到(傳說中,知乎的反爬機制幾乎沒有,是爬蟲愛好者最喜歡爬的網站之一)。
接下來,我們只需要分析網頁原始碼,看看這些資料都藏在哪裡就好了。
二、分析網站原始碼,找到資料存放位置
老規矩,開啟目標網站,按 F12 ,召喚出開發者工具,檢視原始碼,以及監控網路請求。
逛網頁版知乎的時候,我發現(其實大家都能發現),回答數雖有一萬多條,但是網站並不會全部顯示出來,而且也沒有翻頁按鈕,在我們向下滾動頁面到底的時候,後面的回答才會動態的載入出來。
這不就是我們特別喜歡的 Ajax 動態載入的技術嘛?
這種載入方式的原理,簡單通俗點講就是,我伺服器上有很多資料,一下子也發不過去,發過去你也看不完,所以乾脆我分批給你發,你看完一批,然後跟我講,我給你發下一批。瀏覽器就是這樣,每次檢測到你進度條快到底了,趕緊給伺服器發個訊息,把下一批資料拿過來載入上去。
所以我們應付 ajax 的方法也很簡單,截獲瀏覽器發給伺服器的請求,然後分析出請求的規律,然後我們用爬蟲偽裝成瀏覽器不斷向伺服器傳送請求,這樣就可以獲取源源不斷的資料了。
1. 將開發者工具切換到 Network 視窗,清空其中的內容(主要是為了防止干擾),然後不斷的向下拖動頁面的滑動條(讓瀏覽器多向伺服器傳送一些請求,方便我們查詢)。
2. 上圖中便是我篩查到的請求(截圖裡我是做了篩選的,實際上接獲到的請求是相當多的,需要花點功夫去從裡面篩選的),可能有人會疑惑,我怎麼知道哪個請求才是我要的呢?這裡有幾個篩選小技巧。
a. 請求的型別基本都是 XHR 這一型別的,過濾器中選擇這個,可以幫我們過濾到大量的圖片,指令碼,以及網頁樣式檔案等等。
b. 點選請求之後,出現詳情頁,然後切換到 Preview 選項卡,可以預覽該請求返回的內容。我們需要找的請求,返回的內容一般是 json 格式的資料,其中包含了關於知乎回答的一些資訊。
c. 根據以上兩條,基本上稍微花點功夫,很快就可以找到所要找的請求。
3. 分析請求頭的格式(找規律),找到請求頭構成的一般規律,然後我們根據這些規律,構造出剩餘所有的回答資料的請求頭。
第一頁:https://www.zhihu.com/api/v4/questions/275359100/answers?include=data%5B%2A%5D.is_normal%2Cadmin_closed_comment%2Creward_info%2Cis_collapsed%2Cannotation_action%2Cannotation_detail%2Ccollapse_reason%2Cis_sticky%2Ccollapsed_by%2Csuggest_edit%2Ccomment_count%2Ccan_comment%2Ccontent%2Ceditable_content%2Cvoteup_count%2Creshipment_settings%2Ccomment_permission%2Ccreated_time%2Cupdated_time%2Creview_info%2Crelevant_info%2Cquestion%2Cexcerpt%2Crelationship.is_authorized%2Cis_author%2Cvoting%2Cis_thanked%2Cis_nothelp%2Cis_labeled%3Bdata%5B%2A%5D.mark_infos%5B%2A%5D.url%3Bdata%5B%2A%5D.author.follower_count%2Cbadge%5B%2A%5D.topics&limit=5&offset=0&platform=desktop&sort_by=default
第二頁:https://www.zhihu.com/api/v4/questions/275359100/answers?include=data%5B%2A%5D.is_normal%2Cadmin_closed_comment%2Creward_info%2Cis_collapsed%2Cannotation_action%2Cannotation_detail%2Ccollapse_reason%2Cis_sticky%2Ccollapsed_by%2Csuggest_edit%2Ccomment_count%2Ccan_comment%2Ccontent%2Ceditable_content%2Cvoteup_count%2Creshipment_settings%2Ccomment_permission%2Ccreated_time%2Cupdated_time%2Creview_info%2Crelevant_info%2Cquestion%2Cexcerpt%2Crelationship.is_authorized%2Cis_author%2Cvoting%2Cis_thanked%2Cis_nothelp%2Cis_labeled%3Bdata%5B%2A%5D.mark_infos%5B%2A%5D.url%3Bdata%5B%2A%5D.author.follower_count%2Cbadge%5B%2A%5D.topics&limit=5&offset=5&platform=desktop&sort_by=default
第三頁:https://www.zhihu.com/api/v4/questions/275359100/answers?include=data%5B%2A%5D.is_normal%2Cadmin_closed_comment%2Creward_info%2Cis_collapsed%2Cannotation_action%2Cannotation_detail%2Ccollapse_reason%2Cis_sticky%2Ccollapsed_by%2Csuggest_edit%2Ccomment_count%2Ccan_comment%2Ccontent%2Ceditable_content%2Cvoteup_count%2Creshipment_settings%2Ccomment_permission%2Ccreated_time%2Cupdated_time%2Creview_info%2Crelevant_info%2Cquestion%2Cexcerpt%2Crelationship.is_authorized%2Cis_author%2Cvoting%2Cis_thanked%2Cis_nothelp%2Cis_labeled%3Bdata%5B%2A%5D.mark_infos%5B%2A%5D.url%3Bdata%5B%2A%5D.author.follower_count%2Cbadge%5B%2A%5D.topics&limit=5&offset=10&platform=desktop&sort_by=default
仔細觀察可以發現,三者除了最後 offset 引數不一致外,其餘構成完全一樣,而且 offset 的值還很有規律,每次數字增加 5。然後聯想到請求返回的 json 資料可知,每次請求返回 5 條資料。
4. 思路一下子清晰了,offset 是一個偏移量,表示從第幾條回答開始獲取,每次獲取5條回答,所以下次獲取時 offset 就要加 5 啦。所以我們編寫爬蟲時,用一個迴圈,讓 offset 的值從零開始,每次加 5,一直到總回答數為止,這樣就可以獲取到所有的回答資料了。
三、動手擼程式碼,寫爬蟲
爬蟲我們之前寫過很多遍了,思路都差不多,而且知乎網站對爬蟲真的很友好,完全不設反爬機制,我都沒有用到 代理IP和動態UA,甚至沒有寫延遲函式,近兩萬條資料,直接就順利的跑完了。
全部原始碼獻上,關於程式碼的解釋,可以參考我的其他爬蟲文章,已經講的很詳細了,這裡就不再贅述了,如果還有問題,可以私信或者評論問我。
import requests
import json
import time
import re
import datetime
import pandas as pd
def get_data(url):
'''
功能:訪問 url 的網頁,獲取網頁內容並返回
引數:
url :目標網頁的 url
返回:目標網頁的 html 內容
'''
headers = {
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36',
}
try:
r = requests.get(url, headers=headers)
r.raise_for_status()
return r.text
except requests.HTTPError as e:
print(e)
print("HTTPError")
except requests.RequestException as e:
print(e)
except:
print("Unknown Error !")
def parse_data(html):
'''
功能:提取 html 頁面資訊中的關鍵資訊,並整合一個陣列並返回
引數:html 根據 url 獲取到的網頁內容
返回:儲存有 html 中提取出的關鍵資訊的陣列
'''
json_data = json.loads(html)['data']
comments = []
try:
for item in json_data:
comment = []
comment.append(item['author']['name']) # 姓名
comment.append(item['author']['gender']) # 性別
#comment.append(item['author']['url']) # 個人主頁
comment.append(item['voteup_count']) # 點贊數
comment.append(item['comment_count']) # 評論數
#comment.append(item['url']) # 回答連結
comments.append(comment)
return comments
except Exception as e:
print(comment)
print(e)
def save_data(comments):
'''
功能:將comments中的資訊輸出到檔案中/或資料庫中。
引數:comments 將要儲存的資料
'''
filename = 'Data/comments.csv'
dataframe = pd.DataFrame(comments)
dataframe.to_csv(filename, mode='a', index=False, sep=',', header=False)
#dataframe.to_csv(filename, mode='a', index=False, sep=',', header=['name','gender','user_url','voteup','cmt_count','url'])
def main():
url = 'https://www.zhihu.com/api/v4/questions/275359100/answers?include=data%5B%2A%5D.is_normal%2Cadmin_closed_comment%2Creward_info%2Cis_collapsed%2Cannotation_action%2Cannotation_detail%2Ccollapse_reason%2Cis_sticky%2Ccollapsed_by%2Csuggest_edit%2Ccomment_count%2Ccan_comment%2Ccontent%2Ceditable_content%2Cvoteup_count%2Creshipment_settings%2Ccomment_permission%2Ccreated_time%2Cupdated_time%2Creview_info%2Crelevant_info%2Cquestion%2Cexcerpt%2Crelationship.is_authorized%2Cis_author%2Cvoting%2Cis_thanked%2Cis_nothelp%2Cis_labeled%3Bdata%5B%2A%5D.mark_infos%5B%2A%5D.url%3Bdata%5B%2A%5D.author.follower_count%2Cbadge%5B%2A%5D.topics&limit=5&offset=5&platform=desktop&sort_by=default'
# get total cmts number
html = get_data(url)
totals = json.loads(html)['paging']['totals']
print(totals)
print('---'*10)
page = 0
while(page < totals):
url = 'https://www.zhihu.com/api/v4/questions/275359100/answers?include=data%5B%2A%5D.is_normal%2Cadmin_closed_comment%2Creward_info%2Cis_collapsed%2Cannotation_action%2Cannotation_detail%2Ccollapse_reason%2Cis_sticky%2Ccollapsed_by%2Csuggest_edit%2Ccomment_count%2Ccan_comment%2Ccontent%2Ceditable_content%2Cvoteup_count%2Creshipment_settings%2Ccomment_permission%2Ccreated_time%2Cupdated_time%2Creview_info%2Crelevant_info%2Cquestion%2Cexcerpt%2Crelationship.is_authorized%2Cis_author%2Cvoting%2Cis_thanked%2Cis_nothelp%2Cis_labeled%3Bdata%5B%2A%5D.mark_infos%5B%2A%5D.url%3Bdata%5B%2A%5D.author.follower_count%2Cbadge%5B%2A%5D.topics&limit=5&offset='+ str(page) +'&platform=desktop&sort_by=default'
html = get_data(url)
comments = parse_data(html)
save_data(comments)
print(page)
page += 5
if __name__ == '__main__':
main()
print("完成!!")
四、簡單分析資料
簡單的整理了一下資料,結果如下:
- 一共爬取了 18934 條資料,其中 10555 個是小哥哥,3806 個是小姐姐,還有 4573 個性別未知;
- 這些回答中,有 8390 個使用者是匿名回答;
- 點贊數排名前100的回答中,有 52 個小姐姐,有 38 個小哥哥,10 個性別未知;
- 評論數排名前100的回答中,有 42 個小姐姐,有 51 個小哥哥,7 個性別未知;
基於上述資料,我們可以得出一些結論:
- 此話題下,回答的男生人數是女生人數的 2.77 倍,可以得知,男性對於擇偶標準這個話題更加關注,也更加願意去分享自己的擇偶標準(其實就是變相地在相親嘛,我這個單身單身單身的好哥兒們不也是衝著這個來的嘛!)
- 畢竟這個話題還是有點涉及隱私,難以啟齒的,所以 44.3% 的使用者選擇了匿名回答。
- 論評論數,男生的回答要略優於女生,而論點贊數,小姐姐們的回答則會更高。可能是男生的回答多有抖機靈幽默,比較容易有交流討論的話題性,而女生喜歡貼美美噠照片,引得小哥哥們紛紛點贊收藏罷。
後記
我把爬到的資料結果發給我的單身單身單身的好哥兒們看了之後,好哥兒們感到非常詫異,
因為他看回答前幾個都是妹子,還以為這個話題下的妹子會更多一點呢!
原來在網路上,也改變不了狼多肉少的局面。
如果文章中有哪裡沒有講明白,或者講解有誤的地方,歡迎在評論區批評指正,或者掃描下面的二維碼,加我微信,大家一起學習交流,共同進步。
相關文章
- python爬蟲如何爬知乎的話題?Python爬蟲
- 爬取知乎單個網頁問題和回答網頁
- Python網路爬蟲實戰Python爬蟲
- python網路爬蟲應用_python網路爬蟲應用實戰Python爬蟲
- Python爬蟲新手教程: 知乎文章圖片爬取器Python爬蟲
- 網路爬蟲——爬蟲實戰(一)爬蟲
- 新手爬蟲教程:Python爬取知乎文章中的圖片爬蟲Python
- python網路爬蟲(7)爬取靜態資料詳解Python爬蟲
- python3網路爬蟲開發實戰_Python3 爬蟲實戰Python爬蟲
- 爬蟲實戰——58同城租房資料爬取爬蟲
- 【Python3網路爬蟲開發實戰】6-Ajax資料爬取-4-分析Ajax爬取今日頭條街拍美圖Python爬蟲
- 分散式爬蟲之知乎使用者資訊爬取分散式爬蟲
- Python【爬蟲實戰】提取資料Python爬蟲
- 《Python3網路爬蟲開發實戰》教程||爬蟲教程Python爬蟲
- Python爬蟲實戰:爬取淘寶的商品資訊Python爬蟲
- [Python]爬蟲獲取知乎某個問題下所有圖片並去除水印Python爬蟲
- python3網路爬蟲開發實戰_Python 3開發網路爬蟲(一)Python爬蟲
- python網路爬蟲--爬取淘寶聯盟Python爬蟲
- 乾貨分享!Python網路爬蟲實戰Python爬蟲
- Python網路爬蟲實戰小專案Python爬蟲
- Python網路爬蟲實戰專案大全!Python爬蟲
- Python 3網路爬蟲開發實戰Python爬蟲
- [Python3網路爬蟲開發實戰] 分散式爬蟲原理Python爬蟲分散式
- python爬蟲---網頁爬蟲,圖片爬蟲,文章爬蟲,Python爬蟲爬取新聞網站新聞Python爬蟲網頁網站
- Python爬蟲入門【3】:美空網資料爬取Python爬蟲
- Python網路爬蟲實戰專案大全 32個Python爬蟲專案demoPython爬蟲
- Python網路爬蟲資料採集實戰:Requests和Re庫Python爬蟲
- python爬蟲獲取天氣網實時資料Python爬蟲
- python例項,python網路爬蟲爬取大學排名!Python爬蟲
- 【Python3網路爬蟲開發實戰】6-Ajax資料爬取-1-什麼是AjaxPython爬蟲
- 【Python3網路爬蟲開發實戰】6-Ajax資料爬取-3-Ajax結果提取Python爬蟲
- Python爬蟲實戰詳解:爬取圖片之家Python爬蟲
- 用PYTHON爬蟲簡單爬取網路小說Python爬蟲
- Python網路爬蟲實戰(一)快速入門Python爬蟲
- Python3網路爬蟲開發實戰Python爬蟲
- Python爬蟲訓練:爬取酷燃網視訊資料Python爬蟲
- 網路爬蟲——專案實戰(爬取糗事百科所有文章)爬蟲
- Python 爬蟲實戰Python爬蟲