天天看點

python寫爬蟲思路_Python 爬蟲沒有思路?可以看看這篇文章

可以說爬蟲是學習 Python 的入門必修課。當能獨立寫出第一個完整的爬蟲的時候,我們已經邁出了一大步。因為在這過程中,我們已經學會了如何檢視文檔,學會使用 Python 相關庫的操作,怎樣使用 Chrome 的開發者工具(相關工具)和把抓取的資料儲存到資料庫中等等一系列操作,當然收獲最多的還是學習 Python 的自信心。

下面以抓取知乎圖檔為例,邁出我們自學 Python 爬蟲的第一步。

整體思路

在浏覽知乎的時候,經常會看到一些有趣的問題,例如有什麼萬能表情包?,回答中網友分享了收藏多年的表情。但是近1500多條回答,手動儲存表情不現實,是以使用爬蟲幫我們完成這項工作。

首先我們需要做的是收集此類問題。擷取問題的 ID(URL 中 question 後的 ID),建構爬蟲任務池。收集問題的工作可以交給爬蟲,但是為了抓取的圖檔都符合預期,建議先手動收集此類問題。然後将問題的 ID 存入資料庫中,爬蟲運作時讀庫擷取需要爬取的目标貼。通過寫一個爬蟲,生成任務池多線程調用。将擷取到的答案資料清洗,隻收集答案中的圖檔。本案例我們使用 mongo 資料庫,因為 mongo 資料庫簡單友善,也友善我們之後增減字段。

存入庫中的結構和知乎的類似:答案集合儲存所有答案,每一個答案是一條獨立的文檔。

具體類似這種結構:{

"Answer": [

{

"id": 1,

"question_id": "xxx",

"title": "xxx",

"author": "xxx",

"content: [

"imgUrl",

"..."

]

},

{

"id": 2,

"question_id": "xxx",

"title": "xxx",

"author": "xxx",

"content: [

"imgUrl",

"..."

]

},

...

]

}

其中 Answer 為資料庫的集合,集合中的每一項是一條回答。用這種格式儲存的好處是我們隻需通過貼子的 ID 查詢答案即可,儲存起來也非常友善。

知乎爬蟲

開始之前

在開始之前需要安裝項目依賴,隻用到兩個常用庫:

python3 -m pip install requests pymongo

分别用來請求 URL 和操作資料庫。安裝完成後記得啟動 mongo 服務。

Spider

爬蟲代碼比較簡單,關鍵找到知乎答案的接口,解析即可。而且這個接口也是非常好找的。此處用到 Chrome 的開發者工具。

image

接口也沒有任何加密或權限限制,在請求頭中加入 Cookies 就可以了。

通過 Chrome 開發者工具分析,請求攜帶了如下參數,我們隻用到 limit 和 offset,用來控制接口傳回的數量和傳回的位置。include: data[*].is_normal,admin_closed_comment,reward_info,is_collapsed,annotation_action,annotation_detail,collapse_reason,is_sticky,collapsed_by,suggest_edit,comment_count,can_comment,content,editable_content,voteup_count,reshipment_settings,comment_permission,created_time,updated_time,review_info,relevant_info,question,excerpt,relationship.is_authorized,is_author,voting,is_thanked,is_nothelp,is_labeled,is_recognized,paid_info;data[*].mark_infos[*].url;data[*].author.follower_count,badge[*].topics

offset:

limit: 3

sort_by: default

platform: desktop

完整的請求 URL 是:

https://www.zhihu.com/api/v4/questions/21115811/answers?include=data%5B*%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%2Cis_recognized%2Cpaid_info%3Bdata%5B*%5D.mark_infos%5B*%5D.url%3Bdata%5B*%5D.author.follower_count%2Cbadge%5B*%5D.topics&offset=&limit=3&sort_by=default&platform=desktop

隻要動态更改其中的 question, limit 和 offset 就可以了。通過接口傳回的答案總數,判斷需要翻多少頁,當然也可以通過接口傳回的 next 和 previous 來擷取下一頁或前一頁答案連結。

當然在翻頁抓取的時候切記設定睡眠時間,放在伺服器上爬的慢一點也沒關系。我們控制好頻率,不要影響到知乎的正常服務。

請求成功後我們就可以根據自己的需求,存儲資料了,至于如何判斷答案中是否有圖檔,可以參考以下代碼。

使用到了 lxml 庫,也可以使用 re 庫代替。# 部分代碼

@staticmethod

def parse_content(content):

"""解析答案中的 content,直接擷取圖檔"""

if``"

img_list = set(etree.HTML(content).xpath("//img/@data-original"))

return list(img_list)

else:

return []

先判斷回答中是否有 img 标簽,如果沒有直接傳回空清單,如果有的話,通過 data-original屬性擷取原始大小的圖檔連結。也是傳回一個包含圖檔連結的清單。

在入庫的時候,我們通過 parse_content 的傳回判斷是否需要入庫,如果是 [] 就跳過,如果清單不為空就入庫。這樣在之後根據作者展示資料的時候不會隻顯示作者資訊,卻沒有回答的情況了(其實是該作者回答中隻有問題沒有圖檔)。

調用爬蟲

當我們完成上述操作,就可以單獨寫一個檔案使用多線程調用爬蟲了。from concurrent.futures import``ThreadPoolExecutor

qid_list = db.get_all_question()

crawler_list = [ZhihuSpider(qid).run for qid in qid_list]

with``ThreadPoolExecutor(max_workers=4) as executor:

future = [executor.submit(task) for task in crawler_list]

for f in future:

f.result()

qid_list 來自查庫擷取所有的知乎貼子 ID。使用 concurrent.futures 庫并行執行任務,在我們的代碼裡使用 ThreadPoolExecutor,它使用線程池來異步執行調用。 max_workers 控制最多線程的使用,本例中使用最多4個線程執行任務。 ThreadPoolExecutor 讓我們使用多線程時更加簡單。具體文檔見 ThreadPoolExecutor。

總結

最後總結一下整體思路:我們先把需要抓取的 ID 存入資料庫,作為任務池,爬蟲調取任務池中的 ID,将爬取結果再儲存到資料庫。

等我們學會了 Python 爬蟲,再學 Web 開發的時候,還能将我們抓取的結果展示出來,做一個表情包大全網站。一不小心又學習了 Python Web 開發,多好。