Spider 中間件(Middleware) 下載器中間件是介入到 Scrapy 的 spider 處理機制的鉤子框架,您可以添加代碼來處理發(fā)送給 Spiders 的 response 及 spider 產(chǎn)生的 item 和 request。
要啟用 spider 中間件,您可以將其加入到 SPIDER_MIDDLEWARES
設(shè)置中。該設(shè)置是一個字典,鍵位中間件的路徑,值為中間件的順序(order)。
樣例:
SPIDER_MIDDLEWARES = {
'myproject.middlewares.CustomSpiderMiddleware': 543,
}
SPIDER_MIDDLEWARES
設(shè)置會與 Scrapy 定義的 SPIDER_MIDDLEWARES_BASE
設(shè)置合并(但不是覆蓋), 而后根據(jù)順序(order)進(jìn)行排序,最后得到啟用中間件的有序列表: 第一個中間件是最靠近引擎的,最后一個中間件是最靠近 spider 的。
關(guān)于如何分配中間件的順序請查看 SPIDER_MIDDLEWARES_BASE
設(shè)置,而后根據(jù)您想要放置中間件的位置選擇一個值。 由于每個中間件執(zhí)行不同的動作,您的中間件可能會依賴于之前(或者之后)執(zhí)行的中間件,因此順序是很重要的。
如果您想禁止內(nèi)置的(在 SPIDER_MIDDLEWARES_BASE
中設(shè)置并默認(rèn)啟用的)中間件,您必須在項目的 SPIDER_MIDDLEWARES
設(shè)置中定義該中間件,并將其值賦為 None。例如,如果您想要關(guān)閉 off-site 中間件:
SPIDER_MIDDLEWARES = {
'myproject.middlewares.CustomSpiderMiddleware': 543,
'scrapy.contrib.spidermiddleware.offsite.OffsiteMiddleware': None,
}
最后,請注意,有些中間件需要通過特定的設(shè)置來啟用。更多內(nèi)容請查看相關(guān)中間件文檔。
編寫 spider 中間件十分簡單。每個中間件組件是一個定義了以下一個或多個方法的 Python 類:
當(dāng) response 通過 spider 中間件時,該方法被調(diào)用,處理該 response。
process_spider_input()
應(yīng)該返回 None 或者拋出一個異常。
如果其返回 None
,Scrapy 將會繼續(xù)處理該 response,調(diào)用所有其他的中間件直到 spider 處理該 response。
如果其跑出一個異常(exception),Scrapy 將不會調(diào)用任何其他中間件的 process_spider_input()
方法,并調(diào)用 request 的 errback。 errback 的輸出將會以另一個方向被重新輸入到中間件鏈中,使用 process_spider_output()
方法來處理,當(dāng)其拋出異常時則帶調(diào)用 process_spider_exception()
。
參數(shù):
Response
對象) – 被處理的 responseSpider
對象) – 該 response 對應(yīng)的 spider當(dāng) Spider 處理 response 返回 result 時,該方法被調(diào)用。
process_spider_output()
必須返回包含 Request
或 Item
對象的可迭代對象(iterable)。
參數(shù):
Response
對象) – 生成該輸出的 responseRequest
或 Item
對象的可迭代對象(iterable)) – spider 返回的 resultSpider
對象) – 其結(jié)果被處理的 spider當(dāng) spider 或(其他 spider 中間件的) process_spider_input()
跑出異常時, 該方法被調(diào)用。
process_spider_exception()
必須要么返回 None
, 要么返回一個包含 Response
或 Item
對象的可迭代對象(iterable)。
如果其返回 None
,Scrapy 將繼續(xù)處理該異常,調(diào)用中間件鏈中的其他中間件的 process_spider_exception()
方法,直到所有中間件都被調(diào)用,該異常到達(dá)引擎(異常將被記錄并被忽略)。
如果其返回一個可迭代對象,則中間件鏈的 process_spider_output()
方法被調(diào)用, 其他的 process_spider_exception()
將不會被調(diào)用。
參數(shù):
Response
對象) – 異常被拋出時被處理的 responseException
對象) – 被跑出的異常Spider
對象) – 拋出該異常的 spider該方法以 spider 啟動的 request 為參數(shù)被調(diào)用,執(zhí)行的過程類似于 process_spider_output()
,只不過其沒有相關(guān)聯(lián)的 response 并且必須返回 request(不是 item)。
其接受一個可迭代的對象(start_requests 參數(shù))且必須返回另一個包含 Request
對象的可迭代對象。
注解
當(dāng)在您的 spider 中間件實現(xiàn)該方法時, 您必須返回一個可迭代對象(類似于參數(shù) start_requests)且不要遍歷所有的
start_requests
。該迭代器會很大(甚至是無限),進(jìn)而導(dǎo)致內(nèi)存溢出。Scrapy 引擎在其具有能力處理 start request 時將會拉起 request,因此 start request 迭代器會變得無限,而由其他參數(shù)來停止 spider( 例如時間限制或者 item/page 記數(shù))。
參數(shù):
Request
的可迭代對象) – start requestsSpider
對象) – start requests 所屬的 spider本頁面介紹了 Scrapy 自帶的所有 spider 中間件。關(guān)于如何使用及編寫您自己的中間件,請參考 spider middleware usage guide。
關(guān)于默認(rèn)啟用的中間件列表(及其順序)請參考 SPIDER_MIDDLEWARES_BASE
設(shè)置。
DepthMiddleware 是一個用于追蹤每個 Request 在被爬取的網(wǎng)站的深度的中間件。 其可以用來限制爬取深度的最大深度或類似的事情。
DepthMiddleware
可以通過下列設(shè)置進(jìn)行配置(更多內(nèi)容請參考設(shè)置文檔):
DEPTH_LIMIT
- 爬取所允許的最大深度,如果為 0,則沒有限制。DEPTH_STATS
- 是否收集爬取狀態(tài)。DEPTH_PRIORITY
- 是否根據(jù)其深度對 requet 安排優(yōu)先級過濾出所有失敗(錯誤)的 HTTP response,因此 spider 不需要處理這些 request。 處理這些 request 意味著消耗更多資源,并且使得 spider 邏輯更為復(fù)雜。
根據(jù) HTTP 標(biāo)準(zhǔn),返回值為 200-300 之間的值為成功的 resonse。
如果您想處理在這個范圍之外的 response,您可以通過 spider 的 handle_httpstatus_list
屬性或 HTTPERROR_ALLOWED_CODES
設(shè)置來指定 spider 能處理的 response 返回值。
例如,如果您想要處理返回值為 404 的 response 您可以這么做:
class MySpider(CrawlSpider):
handle_httpstatus_list = [404]
Request.meta
中的 handle_httpstatus_list
鍵也可以用來指定每個 request 所允許的 response code。
不過請記住,除非您知道您在做什么,否則處理非 200 返回一般來說是個糟糕的決定。
更多內(nèi)容請參考:HTTP Status Code 定義。
默認(rèn):[]
忽略該列表中所有非 200 狀態(tài)碼的 response。
默認(rèn):False
忽略所有 response,不管其狀態(tài)值。
過濾出所有 URL 不由該 spider 負(fù)責(zé)的 Request。
該中間件過濾出所有主機名不在 spider 屬性 allowed_domains
的 request。
當(dāng) spide 返回一個主機名不屬于該 spider 的 request 時, 該中間件將會做一個類似于下面的記錄:
DEBUG: Filtered offsite request to 'www.othersite.com': <GET http://www.othersite.com/some/page.html>
為了避免記錄太多無用信息,其將對每個新發(fā)現(xiàn)的網(wǎng)站記錄一次。因此,例如,如果過濾出另一個 www.othersite.com
請求,將不會有新的記錄 但如果過濾出 someothersite.com
請求,仍然會有記錄信息(僅針對第一次)。
如果 spider 沒有定義 allowed_domains
屬性,或該屬性為空,則 offsite 中間件將會允許所有 request。
如果 request 設(shè)置了 dont_filter
屬性,即使該 request 的網(wǎng)站不在允許列表里,則 offsite 中間件將會允許該 request。
根據(jù)生成 Request 的 Response 的 URL 來設(shè)置 Request Referer
字段。
默認(rèn):True
是否啟用 referer 中間件。
過濾出 URL 長度比 URLLENGTH_LIMIT 的 request。
UrlLengthMiddleware
可以通過下列設(shè)置進(jìn)行配置(更多內(nèi)容請參考設(shè)置文檔):
URLLENGTH_LIMIT
- 允許爬取 URL 最長的長度。