本筆記寫於2020年2月4日。Python版本為3.7.4,編輯器是VS code
主要參考資料有:
B站視頻av44518113
Python官方文檔
PS:如果筆記中有任何錯誤,歡迎在評論中指出,我會及時回復並修改,謝謝
問題描述
看B站學習視頻的時候,老師講得第一個實戰也就是爬取拉勾網數據是怎么也爬取不下來,彈幕里的方法也都不管用。所以開始求助偉大的度娘,度娘中大部分的解決方法都是使用requests庫來爬取的,但目前只學習的urllib庫,所以沒辦法采用。
但是,我注意到了一個非常重要的細節,就是爬取不下來數據的原因。拉勾網的Cookie中使用了時間戳,簡單的說,就是拉鈎網的cookie中有一個cookie是專門設置時間值的。
正常瀏覽器訪問頁面的時候,瀏覽器首先獲取到了python職位頁面對應的HTML文本,再根據HTML文本中的鏈接請求相應的各種其他數據,然后通過JS代碼將其復原為完整頁面。正常請求過程中,這個速度是非常快速的,時間值並不會過期。也就是說,時間值的設置對於拉勾網的正常訪問不會有任何影響。
但如果按照老師的視頻中所說的,我們直接去爬取保存着職位信息的json數據,就算是復制了所有的響應頭也沒有用,因為cookie中的時間值已經過期了。服務器接受到這種爬蟲請求后,就會返回您操作太頻繁,請稍后再訪問這句話了。
解決辦法
爬取拉勾網數據的關鍵就是快,只要時間戳沒有超期就可以爬取成功。
我們這里分三個步驟:
- 爬取拉勾網的Python職位頁面
- 提取上面爬取到頁面的時間戳cookie
- 將時間戳cookie添加到請求頭中,再請求保存着職位的
json數據
獲取python職位頁面
這一步的目的只有一個,就是找到代表時間值的cookie。
首先通過程序,我們來看一下返回回來的響應頭都有什么?
from urllib import request
import ssl
# 去掉全局安全校驗
ssl._create_default_https_context = ssl._create_unverified_context
url = 'https://www.lagou.com/jobs/list_python?labelWords=&fromSearch=true&suginput='
req = request.Request(url, headers={
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36'
})
# 開始請求
response = request.urlopen(req)
for header in response.getheaders():
print(header)
結果如下:

可以看到共有4個Set-Cookie的響應頭,其中我覺得可能表示時間值的響應頭是user_trace_token,因為我從里面看到了時間信息20200204184124這個時間戳(但我也不確定)。
提取Cookie
既然找到了響應頭,我們接下來就要提取cookie,並構造接下來請求頭的cookie。
cookie = ''
for header in response.getheaders():
if header[0] == 'Set-Cookie':
print(header[1].split(';')[0])
cookie = cookie + header[1].split(';')[0] + '; '
cookie = cookie[:-1]
print(cookie)
結果如下:

接下來和老師的代碼就沒什么區別了,就是要在我們構造的請求頭里加上我們剛才提取的cookie
全代碼示例
# -*- coding: utf-8 -*-
from urllib import request
from urllib import parse
import ssl
# 去掉全局安全校驗
ssl._create_default_https_context = ssl._create_unverified_context
# 先爬取首頁python職位的網站以獲取Cookie
url = 'https://www.lagou.com/jobs/list_python?labelWords=&fromSearch=true&suginput='
req = request.Request(url, headers={
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36'
})
response = request.urlopen(req)
# 從響應頭中提取Cookie
cookie = ''
for header in response.getheaders():
if header[0] == 'Set-Cookie':
cookie = cookie + header[1].split(';')[0] + '; '
# 去掉最后的空格
cookie = cookie[:-1]
# 爬取職位數據
url = 'https://www.lagou.com/jobs/positionAjax.json?city=%E5%8C%97%E4%BA%AC&needAddtionalResult=false'
# 構造請求頭,將上面提取到的Cookie添加進去
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36',
'Cookie': cookie,
'Referer': 'https://www.lagou.com/jobs/list_python?labelWords=&fromSearch=true&suginput='
}
data = {
'first': 'true',
'pn': 1,
'kd': 'python'
}
req = request.Request(url, data=parse.urlencode(data).encode('utf-8'), headers=headers)
response = request.urlopen(req)
print(response.read().decode('utf-8'))
爬取成功后的結果:

