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