關(guān)于python scrapy中添加cookie踩坑記錄
問題發(fā)現(xiàn):
前段時(shí)間項(xiàng)目中,為了防止被封號(提供的可用賬號太少),對于能不登錄就可以抓取的內(nèi)容采用不帶cookie的策略,只有必要的內(nèi)容才帶上cookie去訪問。
本來想著很簡單:在每個(gè)拋出來的Request的meta中帶上一個(gè)標(biāo)志位,通過在CookieMiddleware中查看這個(gè)標(biāo)志位,決定是否是給這個(gè)Request是否裝上Cookie。
實(shí)現(xiàn)的代碼大致如下:
class CookieMiddleware(object):
"""
每次請求都隨機(jī)從賬號池中選擇一個(gè)賬號去訪問
"""
def __init__(self):
client = pymongo.MongoClient(MONGO_URI)
self.account_collection = client[MONGO_DATABASE][ACCOUNT_COLLECTION]
def process_request(self, request, spider):
if 'target' in request.meta:
logging.debug('進(jìn)入到process_request了')
flag = request.meta['target']
if flag != 'no':
all_count = self.account_collection.find({'status': 'success'}).count()
if all_count == 0:
raise Exception('當(dāng)前賬號池為空')
random_index = random.randint(0, all_count - 1)
random_account = self.account_collection.find({'status': 'success'})[random_index]
request.cookies = json.loads(random_account['cookie'])
else:
logging.debug('對XXX的請求不做處理')
else:
all_count = self.account_collection.find({'status': 'success'}).count()
if all_count == 0:
raise Exception('當(dāng)前賬號池為空')
random_index = random.randint(0, all_count - 1)
random_account = self.account_collection.find({'status': 'success'})[random_index]
request.cookies = json.loads(random_account['cookie'])
在settings.py中的配置如下:
DOWNLOADER_MIDDLEWARES = {
'eyny.middlewares.CookieMiddleware': 550,
}
到這里可能有些大佬已經(jīng)能夠看出端倪了,和我一樣認(rèn)為這么寫沒啥問題的同志們繼續(xù)往下看。
在這么編寫完之后,我正常開啟了項(xiàng)目,還適當(dāng)調(diào)高了并發(fā)量,然后第二天發(fā)現(xiàn)賬號被封了。在debug過程中看到在抓取不需要攜帶cookie的url的時(shí)候,依然攜帶了cookie,并且cookie是被放在了header中,經(jīng)過我花費(fèi)了兩個(gè)多小時(shí)查看框架源碼之后,終于發(fā)現(xiàn)了原因。
原因&解決方案:
在scrapy的settings目錄下的default_settings.py文件中,初始聲明了一些DOWNLOADER_MIDDLEWARES_BASE,這些middlewares的聲明如下:
DOWNLOADER_MIDDLEWARES_BASE = {
# Engine side
'scrapy.downloadermiddlewares.robotstxt.RobotsTxtMiddleware': 100,
'scrapy.downloadermiddlewares.httpauth.HttpAuthMiddleware': 300,
'scrapy.downloadermiddlewares.downloadtimeout.DownloadTimeoutMiddleware': 350,
'scrapy.downloadermiddlewares.defaultheaders.DefaultHeadersMiddleware': 400,
'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware': 500,
'scrapy.downloadermiddlewares.retry.RetryMiddleware': 550,
'scrapy.downloadermiddlewares.ajaxcrawl.AjaxCrawlMiddleware': 560,
'scrapy.downloadermiddlewares.redirect.MetaRefreshMiddleware': 580,
'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware': 590,
'scrapy.downloadermiddlewares.redirect.RedirectMiddleware': 600,
'scrapy.downloadermiddlewares.cookies.CookiesMiddleware': 700,
'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware': 750,
'scrapy.downloadermiddlewares.stats.DownloaderStats': 850,
'scrapy.downloadermiddlewares.httpcache.HttpCacheMiddleware': 900,
# Downloader side
}
可以看到在DOWNLOADER_MIDDLEWARES_BASE中也聲明了一個(gè)CookiesMiddleware,而且是700,也就是說比我們寫的CookieMiddleware(500)要靠后執(zhí)行,而且在debug過程中也看到,在執(zhí)行完我們編寫的CookieMiddleware之后,header中沒有攜帶cookie,但是在執(zhí)行完scrapy.downloadermiddlewares.cookies.CookiesMiddleware: 700之后,在header中看到了cookie,這說明cookie是scrapy幫我們自動(dòng)加了。
我們打開scrapy.downloadermiddlewares.cookies.CookiesMiddleware的實(shí)現(xiàn)源碼,主要關(guān)注process_request方法:
class CookiesMiddleware(object):
"""This middleware enables working with sites that need cookies"""
def __init__(self, debug=False):
self.jars = defaultdict(CookieJar)
self.debug = debug
@classmethod
def from_crawler(cls, crawler):
if not crawler.settings.getbool('COOKIES_ENABLED'):
raise NotConfigured
return cls(crawler.settings.getbool('COOKIES_DEBUG'))
def process_request(self, request, spider):
if request.meta.get('dont_merge_cookies', False):
return
cookiejarkey = request.meta.get("cookiejar")
jar = self.jars[cookiejarkey]
cookies = self._get_request_cookies(jar, request)
for cookie in cookies:
jar.set_cookie_if_ok(cookie, request)
# set Cookie header
request.headers.pop('Cookie', None)
jar.add_cookie_header(request)
self._debug_cookie(request, spider)
def process_response(self, request, response, spider):
if request.meta.get('dont_merge_cookies', False):
return response
# extract cookies from Set-Cookie and drop invalid/expired cookies
cookiejarkey = request.meta.get("cookiejar")
jar = self.jars[cookiejarkey]
jar.extract_cookies(response, request)
self._debug_set_cookie(response, spider)
return response
在上面的代碼中,最中要的是process_request方法中的內(nèi)容,可以看到首先從request.meta中查看有沒有dont_merge_cookies屬性,如果沒有或者為false,就不運(yùn)行剩下的方法,臥槽,這就是我們要找的方法呀!是不是好簡單…
特別注意:如果要使用dont_merge_cookies=true,那么需要我們自己將cookie加入到header中,通過**request.cookies = json.loads(random_account[‘cookie'])**方式添加的cookie,scrapy也不再會(huì)幫我們合并到header 中了。
解決方案:我們的解決方法就是在request的meta中加入dont_merge_cookies屬性,并設(shè)置為true,在CookieMiddleware中,我們將cookie添加在header中,而不是賦值給request.cookies
問題解決了,但是這么簡單是不是很不爽,所以就繼續(xù)想看看是為什么scrapy可以自動(dòng)給我們加上cookie,這個(gè)接下來就需要讀下面的代碼了。
總結(jié)
到此這篇關(guān)于關(guān)于python scrapy中添加cookie踩坑記錄的文章就介紹到這了,更多相關(guān)scrapy cookie問題內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
python實(shí)現(xiàn)畫五角星和螺旋線的示例
今天小編就為大家分享一篇python實(shí)現(xiàn)畫五角星和螺旋線的示例,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-01-01
Tensorflow 實(shí)現(xiàn)將圖像與標(biāo)簽數(shù)據(jù)轉(zhuǎn)化為tfRecord文件
今天小編就為大家分享一篇Tensorflow 實(shí)現(xiàn)將圖像與標(biāo)簽數(shù)據(jù)轉(zhuǎn)化為tfRecord文件,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-02-02
python基于Selenium的web自動(dòng)化框架
這篇文章主要介紹了python基于Selenium的web自動(dòng)化框架,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07
Python中的Numeric包和Numarray包使用教程
這篇文章主要介紹了Python中的Numeric包和Numarray包使用教程,來自IBM官方網(wǎng)站上的技術(shù)文檔,需要的朋友可以參考下2015-04-04
在Python中執(zhí)行系統(tǒng)命令的方法示例詳解
最近在做那個(gè)測試框架的時(shí)候發(fā)現(xiàn)對python執(zhí)行系統(tǒng)命令不太熟悉,所以想著總結(jié)下,下面這篇文章主要給大家介紹了關(guān)于在Python中執(zhí)行系統(tǒng)命令的方法,需要的朋友可以參考借鑒,下面來一起看看吧。2017-09-09
Python借助with語句實(shí)現(xiàn)代碼段只執(zhí)行有限次
這篇文章主要介紹了Python借助with語句實(shí)現(xiàn)代碼段只執(zhí)行有限次,首先要定義一個(gè)能夠在with語句中使用的類實(shí)現(xiàn)enter和exit,下文詳細(xì)介紹需要的小伙伴可以參考一下2022-03-03
python list中append()與extend()用法分享
列表是以類的形式實(shí)現(xiàn)的?!皠?chuàng)建”列表實(shí)際上是將一個(gè)類實(shí)例化。因此,列表有多種方法可以操作2013-03-03
python反轉(zhuǎn)(逆序)字符串的6種方法詳細(xì)
這篇文章主要介紹了python反轉(zhuǎn)(逆序)字符串的6種方法詳細(xì),需要的朋友可以參考下2021-04-04

