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