使用 Python 抓取知乎美圖(文末含福利)知乎釣魚貼彙總

福利

當我們爬蟲寫好,入庫,併成功展示出來,不知不覺就實現了一個小程序項目:宅宅生活收藏夾

微信搜索小程序:宅宅生活收藏夾。歡迎大家使用。
在這裏插入圖片描述
在這裏插入圖片描述

之前寫到宅宅生活收藏夾的部署方法,見 使用Flask,Nginx,
Gunicorn,Supervisor完成網站部署
。這次介紹一下如何抓取知乎答案,獲取知乎美圖。

本文除 Python 相關庫的使用外,還會涉及到 mongo 數據庫的使用。

因爲宅宅生活收藏夾只是爲了收集知乎釣魚貼的圖片,有針對性,所以不能通過獲取知乎首頁列表全面抓取。當然抓取方式大同小異,把抓取列表改爲知乎首頁也是可以的。

整體思路

首先我們需要收集知乎各類釣魚貼,這一步可以使用爬蟲(通過爬取別人已經收集的釣魚貼,或者各種社區可能已有釣魚貼專欄等)獲取,也可以在瀏覽知乎時,發現合適的貼子手動添加。

我們需要將釣魚貼的 ID 存入數據庫中,爬蟲運行時讀庫獲取需要爬取的目標貼。

通過寫一個爬蟲,生成任務池多線程調用。將獲取到的答案數據清洗,只收集答案中的圖片。

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

具體結構類似這種結構:

{
    "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

分別用來爬蟲和操作數據庫。

安裝完成後記得啓動 mongo 服務。

Spider

爬蟲代碼比較簡單,代碼不過百行,關鍵找到知乎答案的接口,解析即可。而且這個接口也是非常好找的。

用 Chrome 的開發者工具一下就找到了…

[外鏈圖片轉存失敗(img-waDRfOCu-1562419272787)(https://user-images.githubusercontent.com/25655581/60421921-64c30d80-9c1d-11e9-9c45-7e4cdbe1b38a.png)]

而且接口也沒有任何加密或權限限制,在請求頭中加入 Cookies 就可以了。是不是突然覺得很簡單?

只要我們控制好頻率,不要影響到知乎服務就行了。畢竟我們只是想獲取答案而已,不想做其他的。

通過 Chrome 開發者工具分析,請求攜帶了如下參數,我們只用到 limitoffset,用來控制接口返回的數量和返回的位置。

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

我們只要動態更改其中的 questionlimitoffset 就可以了。

我們通過接口返回的答案總數,判斷需要翻多少頁,當然也可以通過接口返回的 nextprevious 來獲取下一頁或前一頁答案鏈接。知乎的接口設計的非常方便啊。

當然在翻頁抓取的時候切記設置睡眠時間,放在服務器上爬的慢一點也沒關係。不要影響到知乎的正常服務

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

使用到了 lxml,也可以使用 re 庫代替。

@staticmethod
def parse_content(self, content):
    """解析答案中的 content,直接獲取圖片"""

    if "<img " in content:
        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,是對 thread 庫的封裝,讓我們使用線程時更加簡單。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章