1. 程式人生 > >Python練手爬蟲系列No.2 抓取知乎問題下所有回答中的圖片(待續)

Python練手爬蟲系列No.2 抓取知乎問題下所有回答中的圖片(待續)

接著上一篇Python練手爬蟲系列No.1 知乎福利收藏夾圖片批量下載,今天我們來按照知乎問題抓圖片!比起收藏夾,更加直接精準。為什麼先抓收藏夾後抓取問題呢,其實是因為知乎的一點限制。
那就是!知乎問題下方的回答是通過動態載入的……普通的靜態網站抓取的辦法是沒辦法獲取到所有的資料的。
那麼怎麼處理呢?我們一起試試。

網頁資料分析

這裡寫圖片描述
這個時候跟我做開啟Firefox瀏覽器,按F12,進入網路模式下,圖上紅框所示。這個時候顯示的內容,是瀏覽器試試載入的資料,我們首先點左上角的垃圾桶清空資料,然後用力將進度條拉倒最下面開始載入新資料
這裡寫圖片描述
點選更多,立刻看到了這一條。這就是我們要找的,載入的請求專案
這裡寫圖片描述


我們立刻檢視下他的屬性細節,可以通過檢視請求頭來尋找線索。
這裡寫圖片描述
首先,這個請求是以get的形式,也就是所有引數通過組合來載入到URL上,我們可以看一下他包含的引數,基本上就是回傳屬性。最終組合的效果就是
https://www.zhihu.com/api/v4/questions/39284255/answers?include=data[].is_normal,is_sticky,collapsed_by,suggest_edit,comment_count,collapsed_counts,reviewing_comments_count,can_comment,content,editable_content,voteup_count,reshipment_settings,comment_permission,mark_infos,created_time,updated_time,relationship.is_authorized,is_author,voting,is_thanked,is_nothelp,upvoted_followees;data[
].author.is_blocking,is_blocked,is_followed,voteup_count,message_thread_token,badge[?(type=best_answerer)].topics&limit=20&offset=43&sort_by=default”
這一大段URL

而請求頭最重要的一個引數就是
【Authorization:”oauth c3cef7c66a1843f8b……”】這一條,因此,我們提前複製下你的電腦上的數值用來測試資料。需要宣告的是,登入與不登入的條件下引數不同。如果只是小規模的抓取,直接複製你電腦上的數值就好了。如果大規模的抓取……這裡不做討論,用你的oauth小心從此上不了知乎……

程式碼測試

import requests
import json
header = {
    "Host": "www.zhihu.com",
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0",
    "Accept-Language": "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3",
    "Accept-Encoding": "gzip, deflate, br",
    "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
    "X-Requested-With": "XMLHttpRequest",
    "Referer": "https://www.zhihu.com/question/39284255",
    "Authorization":"oauth c3cef7c66a1843f8b3a9e6a1e3160e",
    "Connection": "keep-alive"

}
url = 'https://www.zhihu.com/api/v4/questions/39284255/answers?include=data[*].is_normal,is_sticky,collapsed_by,suggest_edit,comment_count,collapsed_counts,reviewing_comments_count,can_comment,content,editable_content,voteup_count,reshipment_settings,comment_permission,mark_infos,created_time,updated_time,relationship.is_authorized,is_author,voting,is_thanked,is_nothelp,upvoted_followees;data[*].author.is_blocking,is_blocked,is_followed,voteup_count,message_thread_token,badge[?(type=best_answerer)].topics&limit=20&offset=43&sort_by=default'

session = requests.session()
session.headers = header
resp = session.get(url)
content = json.loads(resp.content)
print(content)

這裡說個小技巧,header的構建最簡單的辦法就是……把你用瀏覽器檢視時候的請求頭全部寫進去,然後一點一點去掉,找到關鍵要素保留之。這裡訪問頁面使用了requests庫的session功能。具體功能使用方法可以看文件。
這裡的執行結果是
這裡寫圖片描述
也就是說,他回傳的是一段JSON程式碼。立刻 百度下JSON線上解析,解析程式碼

這裡寫圖片描述
JSON的結構化展現,因為圖片並沒有單獨羅列出來,所以不能通過JSON的結構調取,那麼我們就直接用暴力法,上正則篩選吧。

import re
cont_str = resp.text
pattern = re.compile('data-original=\\"(.*?)\\"',re.S)
urls = re.findall(pattern=pattern,string=cont_str)

待續……