Scrapy-發起相同請求得到不同的返回結果原因及解決方法

今天遇到一個玄學問題,使用相同的url,請求頭headers,請求體data,在通過

>> requests.post(url,headers=headers,data=data)

請求的時候,響應沒有問題,而在使用

>> r=scrapy.Request(url,method='POST',headers=headers,body=data)
>> fetch(r)

的時候卻響應403錯誤!?以上代碼均在scrapy shell內運行,經過多次嘗試,發現每當開啓一個新的scrapy shell,第一次的響應是正確的,但是第二次開始就響應403。我們知道,HTTP協議是基於文本的,如果返回的內容不一致,只有兩種可能:

1.HTTP請求不同

2.HTTP請求相同,但是服務器基於時間,請求頻率等其他信息響應不同內容(反爬)

由於我們是在scrapy shell裏調試,不存在頻次過高的問題,且特徵是新的scrapy shell第一次請求沒問題,由此推測scrapy shell第一次和第二次的請求不一致!如何驗證?有兩種方法:

1)scrapy shell調試查看請求頭

我們通過response.request.headers可以查看響應對應的請求的請求頭,或者直接通過request.headers查看請求頭。需要注意的是,fetch()完成之後,request.headers就是剛剛請求的請求頭,

>>> request=scrapy.Request(url,method='POST',headers=headers,body=data)
>>> request.headers
{b'Content-Type': [b'application/json']}
>>> fetch(request)
2020-03-04 20:15:44 [scrapy.core.engine] INFO: Spider opened
2020-03-04 20:15:45 [scrapy.core.engine] DEBUG: Crawled (200) <POST https://study.163.com/p/search/studycourse.json> (referer: None)
>>> request.headers
{b'Content-Type': [b'application/json'], b'Accept': [b'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'], b'Accept-Language': [b'en'], b'User-Agent': [b'Scrapy/1.8.0 (+https://scrapy.org)'], b'Accept-Encoding': [b'gzip,deflate']}
>>> fetch(request)
2020-03-04 20:20:34 [scrapy.core.engine] DEBUG: Crawled (403) <POST https://study.163.com/p/search/studycourse.json> (referer: None)
>>> request.headers
{b'Content-Type': [b'application/json'], b'Accept': [b'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'], b'Accept-Language': [b'en'], b'User-Agent': [b'Scrapy/1.8.0 (+https://scrapy.org)'], b'Accept-Encoding': [b'gzip,deflate'], b'Cookie': [b'NTESSTUDYSI=2998817e52464f8ba0b578d09bc449e3; EDUWEBDEVICE=bffdf353c8ec4f8eb7fc83aef5caf2d1']

可以看到,我們一開始只設置了Content-Type請求頭,而第一次的實際請求頭還包括了scrapy自動生成的User-Agent、Accept等。而第二次請求頭比第一次多了Cookie頭的信息,因此我們推斷正是多了這個cookie我們的後續請求才會出現錯誤。

注意,第一次請求後可通過response.request.headers查看頭,第二次請求由於403錯誤我們的response爲None,只能通過request.headers查看請求頭。

2)Fiddler抓包查看請求頭

Fiddler開啓抓包,分別執行兩次fetch(request),查看對應的條目

 發現多出Cookie字段,與第一種方法得到的結果一致。

那麼爲什麼會出現先後請求不一致的結果呢?因爲scrapy默認會保留之前響應中Set-Cookie的cookie,並在下一次請求時帶上這些cookie。scrapy中如何設置不太清楚,如果是在scrapy的爬蟲類中,我們可以通過

custom_settings={
    'COOKIES_ENABLED' : False,
}

設置當前爬蟲不使用cookie,這樣就不會因爲帶上cookie而出錯啦。

最後,我還是沒太搞懂,這屬於反爬蟲的措施之一嗎,還是服務端的某種邏輯需要?因爲如果是反爬蟲,爲何不第一次就禁止爬蟲訪問?還是說這個cookie就是某種表示我是爬蟲的標誌,如果這樣,爲何不設計成“僅當獲得一個有效的cookie才能獲取相關數據”的模式?總之,這個搞了我很久的問題既有自己對scrapy瞭解不足的原因,也有這個奇怪服務端邏輯的原因。

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