1.總覽,數據流圖:html
2.Engine:引擎負責控制系統全部組件之間的數據流,並在發生某些操做時觸發事件。python
3.Scheduler:調度程序接收來自引擎的請求,並將它們排入隊列,並在以後,當Engine須要的時候,將requests發送給engine。react
4.Downloader:下載器負責提取網頁並將它們饋送到引擎,而後引擎將其發送給spider。web
5.Spiders:蜘蛛是Scrapy用戶編寫的自定義類,用於解析響應並從中提取item項目(也稱爲抓取的項目)或追加的其餘請求。詳情已經在上一篇文章中介紹過了,這裏就不重複了。ajax
6.Item Pipeline:Item Pipeline負責處理被蜘蛛提取的item, 典型的任務包括清理,驗證和持久性(如將項目存儲在數據庫中)。 這一部分在上一篇文章中也詳細的介紹過了。shell
7.Downloader middlewares:下載器中間件是位於引擎和下載器之間的特定的鉤子,當它們從引擎傳遞到下載器時處理請求,以及從下載器傳遞到引擎的響應。使用下載中間件能夠達成以下的目的:數據庫
扔掉一些請求。json
使用下載中間件:windows
7.1 激活下載中間件:後端
設置:
DOWNLOADER_MIDDLEWARES = {'myproject.middlewares.CustomDownloaderMiddleware': 543,}
修改設置的方法,在上一篇博文中有詳細的介紹。
住:
DOWNLOADER_MIDDLEWARES設置與在Scrapy中定義的DOWNLOADER_MIDDLEWARES_BASE設置合併(而且不意味着被覆蓋),而後按順序排序以得到最終的啓用中間件的排序列表:第一個中間件是靠近引擎的第一個中間件,最後一個是一個靠近下載器。換句話說,每一箇中間件的process_request()方法將以增長的中間件順序(100,200,300,...)調用,每一箇中間件的process_response()方法將按降序調用。
要決定分配給中間件的順序,請參閱DOWNLOADER_MIDDLEWARES_BASE設置(在上一篇文章中有詳細的介紹),並根據要插入中間件的位置選擇一個值。順序很重要,由於每一箇中間件都執行不一樣的操做,而您的中間件可能依賴於以前(或後續)正在使用的中間件。
若是要禁用內置中間件(在DOWNLOADER_MIDDLEWARES_BASE中定義並默認啓用的中間件),則必須在項目的DOWNLOADER_MIDDLEWARES設置中定義它,並將None指定爲其值。例如,若是您要禁用用戶代理中間件:
7.2 編寫本身的下載中間件:
原函數位於:class scrapy.downloadermiddlewares.DownloaderMiddleware
每個下載中間件,都定義瞭如下的一個或者多個函數:
7.2.1 process_request(request, spider):
返回 None,返回一個Response對象,返回一個Request對象,或者拋出IgnoreRequest。
每個經過下載中間件的requests請求都要通過這個函數。
若是返回值爲None,則運行其餘的下載中間件,直到有下載處理器能夠執行這個requests請求。
若是返回一個response對象,scrapy就不會再喚醒其餘的process_request()方法或者process_exception()方法,或者其餘的能返回response對象的下載函數,這個response對象將在process_response()函數中被處理。
若是返回一個request對象,scrapy將中止運行process_requests()函數,調度器將從新調度新加入的request對象。
若是引起IgnoreRequest異常,則將調用已安裝的下載器中間件的process_exception()方法。 若是它們都不處理異常,則調用請求(Request.errback)的errback函數。 若是沒有代碼處理引起的異常,它將被忽略,而且不會被記錄(不像其餘異常)。
Parameters: |
|
---|
關於request和spider對象,在上一篇文章中都有詳細的介紹。
7.2.2 process_response
(request, response, spider)
process_response()
返回一個 Response
對象,一個 Request
對象 ,或者升起一個IgnoreRequest異常。
若是它返回一個響應(多是相同的響應,或者是一個全新的響應),那麼響應將繼續用中間件鏈(開頭就提到了,中間件不止一個)中下一個中間件的process_response()來處理。
若是它返回一個Request對象,則中間件鏈將暫停,而且返回的請求將被調度器從新調度以備未來下載。 這與從process_request()返回請求的行爲是同樣的。
若是引起IgnoreRequest異常,則調用請求(Request.errback)的errback函數。 若是沒有代碼處理引起的異常,它將被忽略,而且不會被記錄(不像其餘異常)。
Parameters: |
|
---|
相應的對象都在上一篇文章中都有詳細的介紹。
7.2.3 process_exception
(request, exception, spider):
當下載處理程序或process_request()(來自下載中間件)引起異常(包括IgnoreRequest異常)時,Scrapy調用process_exception()
process_exception()
應該返回 None
,,一個 Response對象,
或者一個 Request
對象。
若是它返回None,Scrapy將繼續處理這個異常,執行已安裝中間件的任何其餘process_exception()方法,直到全部的中間件所有被執行完,默認的異常處理開始。
若是它返回一個Response對象,則啓動已安裝中間件的process_response()方法鏈,Scrapy不會打擾其餘任何中間件的process_exception()方法。
若是它返回一個Request對象,則返回的請求將被調度器從新調用以備未來下載。 這會中止執行中間件的process_exception()方法,就像返回響應同樣。
Parameters: |
---|
接下來,咱們介紹一些scrapy內置的中間件,以便利用他們編寫本身的下載中間件。
7.2.4 CookiesMiddleware:
源文件位於:class scrapy.downloadermiddlewares.cookies.
CookiesMiddleware
這個中間件能夠處理須要cookies的網站,好比那些使用會話的網站。 它跟蹤由Web服務器發送的cookie,並將其發送給(從蜘蛛)後續請求,就像瀏覽器同樣。
如下設置(在setting.py中設置)可用於配置Cookie中間件:
COOKIES_ENABLED
COOKIES_DEBUG
經過使用request()函數中的meta參數,能夠保持每一個蜘蛛的多個cookie會話。 默認狀況下,它使用一個cookie jar(session),可是你能夠傳遞一個標識符來使用不一樣的標識符。
例如:
for i, url in enumerate(urls): yield scrapy.Request(url, meta={'cookiejar': i}, callback=self.parse_page)
請記住,cookiejar元鍵並不會與request函數綁定。 你須要繼續傳遞下去的請求。 例如:
def parse_page(self, response): # do some processing return scrapy.Request("http://www.example.com/otherpage", meta={'cookiejar': response.meta['cookiejar']}, callback=self.parse_other_page)
COOKIES_ENABLED:
默認值:True
是否啓用Cookie中間件。 若是禁用,則不會將cookie發送到Web服務器。
COOKIES_DEBUG:
默認:False
若是啓用,Scrapy會記錄在請求中發送的全部Cookie(即Cookie頭)以及在響應中收到的全部Cookie(即Set-Cookie頭)。
7.2.5 DefaultHeadersMiddleware
源文件位於:
class scrapy.downloadermiddlewares.defaultheaders.
DefaultHeadersMiddleware
該中間件設置在DEFAULT_REQUEST_HEADERS設置中指定的全部默認請求標頭。
7.2.6 DownloadTimeoutMiddleware
源文件位於:class scrapy.downloadermiddlewares.downloadtimeout.
DownloadTimeoutMiddleware
設置下載超時,這個中間件在setting.py中設置DOWNLOAD_TIMEOUT的值,或者設置spider屬性download_timeout 的值。
注:
也可使用download_timeout Request.meta鍵設置每一個請求的下載超時時間; 即便在禁用了DownloadTimeoutMiddleware的狀況下也是如此。
7.2.7 HttpAuthMiddleware
源文件位於:class scrapy.downloadermiddlewares.httpauth.
HttpAuthMiddleware
這個中間件使用基本訪問驗證(又稱HTTP驗證)驗證某些蜘蛛生成的全部請求,要啓用某些蜘蛛的HTTP身份驗證,要設置這些蜘蛛的http_user和http_pass屬性。
例如:
from scrapy.spiders import CrawlSpider class SomeIntranetSiteSpider(CrawlSpider): http_user = 'someuser' http_pass = 'somepass' name = 'intranet.example.com' # .. rest of the spider code omitted ...
7.2.8 HttpCacheMiddleware
源文件位於:class scrapy.downloadermiddlewares.httpcache.
HttpCacheMiddleware
該中間件爲全部的HTTP請求和響應提供低級緩存。 它必須與緩存存儲後端以及緩存策略結合使用。
Scrapy附帶三個HTTP緩存存儲後端:
能夠在setting.py中設置HTTPCACHE_STORAGE來更改HTTP緩存存儲後端。 或者你也能夠實現你本身的存儲後端(這裏就不一一介紹了,具體的內容能夠查看官方文檔)。
Scrapy附帶兩個HTTP緩存策略:
此策略提供符合RFC2616的HTTP緩存,即HTTP緩存控制感知,旨在連續運行,以免下載未修改的數據(以節省帶寬並加速爬網)。
策略具體以下:
不存儲嘗試沒有 no-store cache-control 指令的響應/請求
若是設置了no-cache cache-control指令,即便是最新的響應,也不要從緩存提供響應
根據max-age cache-control計算生存週期
根據Expires響應頭中計算生存週期
使用Last-Modified響應計算生存週期(Firefox使用的啓發式)
根據age響應頭計算當前age值
根據Date頭計算當前的age值
根據Last-Modified響應頭從新驗證陳舊的響應
基於ETag響應頭從新驗證陳舊的響應
爲每個沒有Date頭的響應設置Date頭
在requests中支持max-stale cache-control指令
這使得蜘蛛能夠配置完整的RFC2616緩存策略,可是避免在逐個請求的基礎上進行從新驗證,同時保持與HTTP規範的一致性。
例:
添加緩存控制:max-stale = 600請求標頭接受超過其過時時間不超過600秒的響應。
此政策沒有任何HTTP緩存控制指令的意識。 每一個請求及其相應的響應都被緩存。 當再次看到相同的請求時,響應被返回而不從Internet傳送任何東西。
Dummy策略對於更快速地測試蜘蛛(無需每次都等待下載)以及在Internet鏈接不可用時嘗試離線蜘蛛很是有用。 咱們的目標是可以像之前同樣「重播」蜘蛛跑。
爲了使用這個政策,須要設置:
HTTPCACHE_POLICY
(位於scrapy.extensions.httpcache.DummyPolicy)
能夠在setting.py中設置HTTPCACHE_POLICY更改HTTP緩存策略。 或者你也能夠實施你本身的政策。
禁止緩存,能夠將requests中的meta的dont_cache 的值設爲True來實現。
7.2.9 HttpCompressionMiddleware
源文件位於:class scrapy.downloadermiddlewares.httpcompression.
HttpCompressionMiddleware
該中間件容許從網站發送/接收壓縮(gzip,deflate)流量。
若是安裝了brotlipy,該中間件還支持解碼brotli-compressed響應。
使用這個中間件須要在setting.py中設置COMPRESSION_ENABLED Default: True
7.2.10 HttpProxyMiddleware
源文件位於:class scrapy.downloadermiddlewares.httpproxy.
HttpProxyMiddleware
該中間件經過設置Request對象meta中proxy的值來設置HTTP代理以用於請求。
像Python標準庫模塊urllib和urllib2同樣,它遵照如下環境變量:
http_proxy
https_proxy
no_proxy
您還能夠將每一個請求的meta.proxy設置爲像http:// some_proxy_server:port或http:// username:password @ some_proxy_server:port這樣的值。 請記住,該值將優先於http_proxy / https_proxy環境變量,而且也會忽略no_proxy環境變量。
HttpProxyMiddleware設置:
HTTPPROXY_ENABLED = True HTTPPROXY_AUTH_ENCODING = 'latin-1'
在scrapy.settings.default_setting.py中爲默認設置,能夠在setting.py處作相應的修改,在上篇文章中有詳細的描述。
7.2.11 RedirectMiddleware
源文件位於:class scrapy.downloadermiddlewares.redirect.
RedirectMiddleware
這個中間件根據響應狀態來處理請求的重定向。
請求通過的URL(被重定向)能夠在redirect_urls Request.meta鍵中找到。
RedirectMiddleware能夠經過如下設置進行配置(更多信息請參閱設置文檔,在上篇博文中有詳細的介紹):
REDIRECT_ENABLED
REDIRECT_MAX_TIMES
若是Request.meta將dont_redirect鍵設置爲True,則該中間件將忽略該請求。
若是你想在你的蜘蛛中處理一些重定向狀態碼,你能夠在handle_httpstatus_list spider屬性中指定這些。
例如,若是你想讓重定向中間件忽略301和302響應(並將它們傳遞給你的蜘蛛),你能夠這樣作:
class MySpider(CrawlSpider): handle_httpstatus_list = [301, 302]
Request.meta的handle_httpstatus_list鍵也能夠用來指定在每一個請求的基礎上容許哪些響應碼。 若是想處理任何響應碼的請求,能夠將meta key handle_httpstatus_all設置爲True。
RedirectMiddleware的設置包括:
REDIRECT_ENABLED = True REDIRECT_MAX_TIMES = 20 # uses Firefox default setting REDIRECT_PRIORITY_ADJUST = +2
在scrapy.settings.default_setting.py中爲默認設置,能夠在setting.py處作相應的修改,在上篇文章中有詳細的描述。
7.2.12 MetaRefreshMiddleware
原文位於:class scrapy.downloadermiddlewares.redirect.
MetaRefreshMiddleware
該中間件處理基於html標籤meta-refresh的重定向請求。
MetaRefreshMiddleware能夠經過如下設置在setting.py中進行配置:
METAREFRESH_ENABLED
METAREFRESH_MAXDELAY
該中間件遵照在RedirectMiddleware中描述的requests.meta鍵,REDIRECT_MAX_TIMES設置,dont_redirect和redirect_urls。
MetaRefreshMiddleware的設置包括:
METAREFRESH_ENABLED = True METAREFRESH_MAXDELAY = 100
在scrapy.settings.default_setting.py中爲默認設置,能夠在setting.py處作相應的修改,在上篇文章中有詳細的描述。
7.2.13 RetryMiddleware
源文件位於:class scrapy.downloadermiddlewares.retry.
RetryMiddleware
這個中間件用於重試可能由臨時問題(如鏈接超時或HTTP 500錯誤)致使的失敗請求。
一旦蜘蛛抓取全部常規(非失敗)頁面,抓取過程就收集失敗的頁面,並在最後從新安排。 一旦沒有更多的失敗頁面重試,這個中間件發送一個信號(retry_complete),因此其餘擴展能夠鏈接到該信號。
能夠經過如下設置配置RetryMiddleware:
RETRY_ENABLED
RETRY_TIMES
RETRY_HTTP_CODES
若是Request.meta將dont_retry鍵設置爲True,則該中間件將忽略該請求。
設置包括:
RETRY_ENABLED = True RETRY_TIMES = 2 # initial response + 2 retries = 3 requests RETRY_HTTP_CODES = [500, 502, 503, 504, 408] RETRY_PRIORITY_ADJUST = -1
在scrapy.settings.default_setting.py中爲默認設置,能夠在setting.py處作相應的修改,在上篇文章中有詳細的描述。
7.2.14 RobotsTxtMiddleware
源文件位於:class scrapy.downloadermiddlewares.robotstxt.
RobotsTxtMiddleware
這個中間件使用robots.txt過濾請求。
爲確保Scrapy尊重robots.txt,請確保中間件已啓用且ROBOTSTXT_OBEY設置已啓用。
若是Request.meta將dont_obey_robotstxt鍵設置爲True,則即便啓用ROBOTSTXT_OBEY,該中間件也會忽略該請求。
7.2.15 DownloaderStats
源文件位於:
class scrapy.downloadermiddlewares.stats.
DownloaderStats
存儲全部經過它的請求,響應和異常的統計信息的中間件。
要使用此中間件,您必須啓用DOWNLOADER_STATS設置。
7.2.16 UserAgentMiddleware
源文件位於:class scrapy.downloadermiddlewares.useragent.
UserAgentMiddleware
容許蜘蛛覆蓋默認用戶代理的中間件。
爲了使蜘蛛覆蓋默認的用戶代理,必須設置其user_agent屬性。
7.2.17 AjaxCrawlMiddleware
源文件位於:class scrapy.downloadermiddlewares.ajaxcrawl.
AjaxCrawlMiddleware
這個中間件根據meta-fragment html標籤查找「AJAX可抓取」的特殊頁面,詳情請參見https://developers.google.com/webmasters/ajax-crawling/docs/getting-started。
注:
Scrapy在沒有這個中間件的狀況下能夠找到像「http://example.com/!#foo=bar」這樣的URL的「AJAX可抓取」頁面。 可是當URL不包含「!#」時,AjaxCrawlMiddleware是必需的。 這一般是「索引」或「主」網頁的狀況。
AjaxCrawlMiddleware 的設置:
AJAXCRAWL_ENABLED = False
在scrapy.settings.default_setting.py中爲默認設置,能夠在setting.py處作相應的修改,在上篇文章中有詳細的描述。
一般在進行普遍抓取的時候纔會使用到這個中間件。
注:
關於普遍抓取:
Scrapy的默認設置已針對特定網站進行了優化。這些網站一般由一個單一的Scrapy蜘蛛來處理,雖然這不是必需的或者是必需的(例如,有一些通用的蜘蛛能夠處理任何給定的網站)。
除了這種「重點抓取」以外,還有一種常見的抓取方式,覆蓋了大量(可能無限)的域名,而且只受時間或其餘任意限制,而不是在域名被抓取到完成時停止,當沒有更多的要求執行。這些被稱爲「普遍爬行」,是搜索引擎使用的典型爬蟲。
這些是普遍爬行中常見的一些常見屬性:
如上所述,Scrapy默認設置針對重點抓取進行了優化,而不是普遍抓取。可是,因爲其異步架構,Scrapy很是適合執行快速普遍爬網。官方文檔總結了在使用Scrapy進行普遍搜索時須要注意的一些事項,以及Scrapy設置的具體建議,以便實現高效的全面爬網。
8. Spider Middleware(蜘蛛中間件)
蜘蛛中間件是Scrapy蜘蛛處理機制的鉤子框架,您能夠插入自定義功能來處理髮送給蜘蛛進行處理的response,和從蜘蛛生成的request和item。
使用蜘蛛中間件:
8.1 激活:
在setting.py中設置SPIDER_MIDDLEWARES的屬性爲蜘蛛中間件的路徑。
例如:
SPIDER_MIDDLEWARES = { 'myproject.middlewares.CustomSpiderMiddleware': 543, }
SPIDER_MIDDLEWARES設置與Scrapy中定義的SPIDER_MIDDLEWARES_BASE設置(並不意味着被覆蓋)合併,而後按順序排序以得到最終的啓用中間件排序列表:第一個中間件是靠近引擎的中間件,最後一個是一個靠近蜘蛛。換句話說,每一箇中間件的process_spider_input()方法將以增長的中間件的順序(100,200,300,...)被調用,而且每一箇中間件的process_spider_output()方法將按降序調用。
要決定分配給中間件的順序,請參閱SPIDER_MIDDLEWARES_BASE設置,並根據要插入中間件的位置選擇一個值。順序很重要,由於每一箇中間件都執行不一樣的操做,而您的中間件可能依賴於以前(或後續)正在使用的中間件。
SPIDER_MIDDLEWARES_BASE:
{ 'scrapy.spidermiddlewares.httperror.HttpErrorMiddleware': 50, 'scrapy.spidermiddlewares.offsite.OffsiteMiddleware': 500, 'scrapy.spidermiddlewares.referer.RefererMiddleware': 700, 'scrapy.spidermiddlewares.urllength.UrlLengthMiddleware': 800, 'scrapy.spidermiddlewares.depth.DepthMiddleware': 900, }
若是要禁用內置中間件(在SPIDER_MIDDLEWARES_BASE中定義而且在默認狀況下啓用的中間件),則必須在項目SPIDER_MIDDLEWARES設置中定義它,並將None指定爲其值。例如,若是您要禁用OffsiteMiddleware:
SPIDER_MIDDLEWARES = { 'myproject.middlewares.CustomSpiderMiddleware': 543, 'scrapy.spidermiddlewares.offsite.OffsiteMiddleware': None, }
最後,請記住,某些中間件可能須要經過特定的設置啓用。 有關更多信息,請參閱每一箇中間件文檔。
下面將介紹一些相關的中間件,以便咱們編寫本身的中間件。
8.2 編寫本身的蜘蛛中間件:
蜘蛛中間的原函數位於:class scrapy.spidermiddlewares.
SpiderMiddleware
每一個蜘蛛中間件都至少有如下函數中的一個。
process_spider_input
(response, spider)
這個方法被每個經過蜘蛛中間件進入蜘蛛的response對象喚醒,並對這些響應進行處理。
process_spider_input()的返回值爲None或引起一個異常。
若是它返回None,Scrapy將執行全部其餘中間件處理這個響應,直到響應被傳遞給蜘蛛進行處理。
若是引起異常,Scrapy其餘蜘蛛中間件的process_spider_input()將不會在被喚醒,此時,喚醒request errback。errback的輸出傳遞給process_spider_output(),或者在process_spider_exception()方法中引起異常。
Parameters: |
|
---|
process_spider_output
(response, result, spider):
這個方法被spider處理的結果喚醒,以後處理這些從spider發來的響應。
process_spider_output()必須返回Request,dict或Item的迭代對象。
Parameters: |
|
---|
process_spider_exception
(response, exception, spider)
這個方法被一個蜘蛛或者一個process_spider_input()的異常喚醒。
process_spider_exception()應該返回None或一個Response,dict或Item的迭代對象。
若是它返回None,Scrapy將繼續處理這個異常,在下面的中間件組件中的process_spider_exception()方法,直到沒有中間件組件被遺留,異常到達引擎(它被記錄和丟棄的地方)。
若是它返回一個可迭代的process_spider_output()管道,而且不會調用其餘process_spider_exception()。
Parameters: |
|
---|
process_start_requests
(start_requests, spider)
這個方法是經過spider的start_request請求來調用的,除了沒有關聯response,而且只返回request(不是item)以外,它和process_spider_output()方法相似。
它接收一個迭代(在start_requests參數中),而且必須返回另外一個可迭代的Request對象。
注:
process_start_requests()有什麼用?
在spider中間件中實現這個方法時,你應該老是返回一個iterable(跟在input以後),而不是消耗全部的start_requests迭代器,由於它可能很是大(甚至是無界),這可能會致使內存溢出。 Scrapy引擎被設計爲在有能力處理它們的時候提取啓動請求,因此當有其餘一些中止蜘蛛的條件(好比時間限制或者item / page count)的時候,start_requests迭代器就不會是沒有止盡的了。
Parameters: |
|
---|
8.3 一些內置的蜘蛛中間件:
8.3.1 DepthMiddleware
源碼位於:class scrapy.spidermiddlewares.depth.
DepthMiddleware
DepthMiddleware是一個Scrapy中間件,用於跟蹤站點內部每一個請求的深度。 它能夠用來限制最大的深度或相似的東西。
DepthMiddleware能夠經過如下設置進行配置:
DEPTH_LIMIT
- The maximum depth that will be allowed to crawl for any site. If zero, no limit will be imposed.DEPTH_STATS
- Whether to collect depth stats.DEPTH_PRIORITY
- Whether to prioritize the requests based on their depth.默認設置位於scarpy.setting.default_setting.py,能夠在setting.py中修改設置。
DEPTH_LIMIT = 0 DEPTH_STATS = True DEPTH_PRIORITY
8.3.2 HttpErrorMiddleware
源碼位於:class scrapy.spidermiddlewares.httperror.
HttpErrorMiddleware
過濾掉不成功的(錯誤的)HTTP響應,這樣蜘蛛就沒必要處理它們,減少開銷,並使蜘蛛邏輯更加簡潔。
根據HTTP標準,成功的響應是那些狀態碼在200-300範圍內的響應。
若是您仍想處理該範圍以外的響應代碼,則可使用handle_httpstatus_list spider屬性或HTTPERROR_ALLOWED_CODES(可是這個我在源碼中並無找到,多是和版本有關係)設置來指定蜘蛛可以處理的響應代碼。
例如,若是你想要你的蜘蛛來處理404響應,你能夠這樣作:
class MySpider(CrawlSpider): handle_httpstatus_list = [404]
Request.meta的handle_httpstatus_list關鍵字也能夠用來指定在每一個請求的基礎上容許哪些響應代碼。 若是您想容許請求的任何響應代碼,您也能夠將meta key handle_httpstatus_all設置爲True。
可是請記住,除非你真的知道你在作什麼,不然處理非200的回答一般是一個壞主意。
狀態碼詳細解析:https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
8.3.3 OffsiteMiddleware
源碼位於:
class scrapy.spidermiddlewares.offsite.
OffsiteMiddleware
過濾蜘蛛所涉及域以外的URL請求。
這個中間件過濾出每一個請求的主機名不在蜘蛛的allowed_domains屬性中。allowed_domains 列表中任何域的全部子域也都是容許的。 例如。 規則www.example.org也將容許bob.www.example.org但不是www2.example.com和example.com。
當你的蜘蛛返回一個不屬於蜘蛛所涉及域名的請求時,這個中間件會記錄一條相似於這個的調試信息:
DEBUG: Filtered offsite request to 'www.othersite.com': <GET http://www.othersite.com/some/page.html>
爲了不在日誌中填寫過多的噪音,只會爲每一個新過濾的域打印這些消息之一。 所以,例如,若是過濾了www.othersite.com的另外一個請求,則不會打印日誌消息。 可是,若是過濾了someothersite.com的請求,則會打印一條消息(但僅限於過濾的第一個請求)。
若是蜘蛛沒有定義allowed_domains屬性,或者屬性是空的,異地中間件將容許全部的請求。
若是請求具備設置的dont_filter屬性,則即便其域未在容許的域中列出,OffsiteMiddleware也將容許該請求。
8.3.4 RefererMiddleware
源碼位於:class scrapy.spidermiddlewares.referer.
RefererMiddleware
根據生成它的Response的URL填充Request Referer頭。
RefererMiddleware設置:
REFERER_ENABLED = True REFERRER_POLICY = 'scrapy.spidermiddlewares.referer.DefaultReferrerPolicy'
默認設置位於scarpy.setting.default_setting.py,能夠在setting.py中修改設置。
您還可使用特殊的「referrer_policy」 Request.meta鍵爲每一個請求設置Referrer策略,其值與REFERRER_POLICY設置相同。
REFERRER_POLICY的可接受值
要麼是一個scrapy.spidermiddlewares.referer.ReferrerPolicy子類的路徑 - 一個自定義策略或一個內置的策略(參見下面的類),
或者W3C定義的標準字符串值之一,
或特殊的「scrapy-default」。
class scrapy.spidermiddlewares.referer.
DefaultReferrerPolicy
「no-referrer-when-downgrade」的變體,按照no-referrer-when-downgrade策略添加refer頭,可是當父請求是file://
或者s3://
scheme是,refer請求頭將不會被髮送。這個策略可能會致使跨域訪問,若是要保證同源策略,那麼應該選用「same-origin」策略。
class scrapy.spidermiddlewares.referer.
NoReferrerPolicy
最簡單的策略是「NoReferrerPolicy」,它不引用任何引用信息以及從特定請求客戶端向任何源發出的請求。 refer標題將被徹底省略。
class scrapy.spidermiddlewares.referer.
NoReferrerWhenDowngradePolicy
使用「no-referrer-when-downgrade」策略發送refer頭部。
class scrapy.spidermiddlewares.referer.SameOriginPolicy
「同源」策略規定,當從特定請求客戶端發出同源請求時,將剝離完整URL做爲引用者信息,另外一方面,跨境請求將不包含引薦來源信息。 Referer HTTP標頭將不會被髮送。
class scrapy.spidermiddlewares.referer.
OriginPolicy
「OriginPolicy」策略規定,當從特定的請求客戶端發出同源請求和跨源請求時,只有請求客戶端源的ASCII序列被做爲引用者信息發送。
class scrapy.spidermiddlewares.referer.
StrictOriginPolicy
"StrictOriginPolicy」策略在發出請求時發送請求客戶端的來源的ASCII序列:
從受TLS保護的環境設置對象到可能可信的URL,以及
從非TLS保護的環境設置對象到任何來源。
另外一方面,從受TLS保護的請求客戶端請求非潛在可信的URL將不包含引薦者信息。 Referer HTTP標頭將不會被髮送。
class scrapy.spidermiddlewares.referer.
OriginWhenCrossOriginPolicy
僅在發生跨域訪問時發送只包含 host 的 Referrer,同域下仍是完整的。它與 Origin Only
的區別是多判斷了是否 Cross-origin
。須要注意的是協議、域名和端口都一致,纔會被瀏覽器認爲是同域;
class scrapy.spidermiddlewares.referer.
StrictOriginWhenCrossOriginPolicy
「strict-origin-when-cross-origin」策略規定,當從特定的請求客戶端發出同源請求時,剝離用做引用者的完整URL做爲引用者信息發送,而且只有 請求客戶端進行跨域請求時的來源:
從受TLS保護的環境設置對象到可能可信的URL,以及
從非TLS保護的環境設置對象到任何來源。
另外一方面,來自受TLS保護的客戶端請求不可信的URL將不包含引薦者信息。 Referer HTTP標頭將不會被髮送。
class scrapy.spidermiddlewares.referer.
UnsafeUrlPolicy
不管是否發生協議降級,不管是本站連接仍是站外連接,通通都發送 Referrer 信息。正如其名,這是最寬鬆而最不安全的策略;
策略參考連接:
https://www.w3.org/TR/referrer-policy
https://imququ.com/post/referrer-policy.html
8.3.5 UrlLengthMiddleware
class scrapy.spidermiddlewares.urllength.
UrlLengthMiddleware
過濾URL長度大於URLLENGTH_LIMIT的請求
UrlLengthMiddleware能夠經過如下設置進行配置(更多信息請參閱上一篇博文):
URLLENGTH_LIMIT - 容許抓取的網址的最大網址長度。
9. Extensions
擴展框架提供了一種將您本身的自定義功能插入Scrapy的機制。
擴展只是在擴展初始化時在Scrapy啓動時實例化的常規類。
9.1 Extensions設置
擴展程序使用Scrapy setting.py來管理其設置,就像任何其餘Scrapy代碼同樣。
擴展名習慣是以本身的名字爲前綴設置,以免與現有的(和未來的)擴展名相沖突。 例如,處理Google Sitemaps的假設性擴展將使用像GOOGLESITEMAP_ENABLED,GOOGLESITEMAP_DEPTH等設置。
9.2 導入並激活拓展功能
實例化:
擴展在啓動時經過實例化擴展類的單個實例來加載和激活。 所以,全部的擴展初始化代碼都必須在類構造函數(__init__方法)中執行。
激活:
在setting.py中添加EXTENSIONS的路徑,例如:
EXTENSIONS = { 'scrapy.extensions.corestats.CoreStats': 500, 'scrapy.extensions.telnet.TelnetConsole': 500, }
{ 'scrapy.extensions.corestats.CoreStats': 0, 'scrapy.extensions.telnet.TelnetConsole': 0, 'scrapy.extensions.memusage.MemoryUsage': 0, 'scrapy.extensions.memdebug.MemoryDebugger': 0, 'scrapy.extensions.closespider.CloseSpider': 0, 'scrapy.extensions.feedexport.FeedExporter': 0, 'scrapy.extensions.logstats.LogStats': 0, 'scrapy.extensions.spiderstate.SpiderState': 0, 'scrapy.extensions.throttle.AutoThrottle': 0, }
不一樣的拓展一般是不相干的,全部,順序值都爲0,若是要添加相互關聯的拓展,則須要更改順序值。
若是要禁用拓展,則在extensions中將相關的拓展的順序值設爲:None。
9.3 編寫本身的拓展:
這裏咱們將實現一個簡單的擴展來講明上一節中描述的概念。 這個擴展將每次記錄一條消息:
該extensions將經過MYEXT_ENABLED設置啓用,項目數將經過MYEXT_ITEMCOUNT設置指定。
這裏是這種擴展的代碼:
import logging from scrapy import signals from scrapy.exceptions import NotConfigured logger = logging.getLogger(__name__) class SpiderOpenCloseLogging(object): def __init__(self, item_count): self.item_count = item_count self.items_scraped = 0 @classmethod def from_crawler(cls, crawler): # first check if the extension should be enabled and raise
# NotConfigured otherwise
if not crawler.settings.getbool('MYEXT_ENABLED'): raise NotConfigured # get the number of items from settings
item_count = crawler.settings.getint('MYEXT_ITEMCOUNT', 1000) # instantiate the extension object
ext = cls(item_count) # connect the extension object to signals
crawler.signals.connect(ext.spider_opened, signal=signals.spider_opened) crawler.signals.connect(ext.spider_closed, signal=signals.spider_closed) crawler.signals.connect(ext.item_scraped, signal=signals.item_scraped) # return the extension object
return ext def spider_opened(self, spider): logger.info("opened spider %s", spider.name) def spider_closed(self, spider): logger.info("closed spider %s", spider.name) def item_scraped(self, item, spider): self.items_scraped += 1
if self.items_scraped % self.item_count == 0: logger.info("scraped %d items", self.items_scraped)
9.4 內置的拓展:
9.4.1 Log Stats extension
源碼位於:class scrapy.extensions.logstats.
LogStats
記錄抓取的頁面和抓取的items等基本統計信息。
9.4.2 Core Stats extension
源碼位於:class scrapy.extensions.corestats.
CoreStats
核心信息收集
9.4.3 Memory usage extension
源碼位於:class scrapy.extensions.memusage.
MemoryUsage
注:這個拓展在windows下是不能工做的。
監控在scrapy使用期間內核的使用狀況。
相關的設置有:
MEMUSAGE_ENABLED = True MEMUSAGE_LIMIT_MB = 0 MEMUSAGE_NOTIFY_MAIL = [] MEMUSAGE_WARNING_MB = 0
9.4.4 Memory debugger extension
源碼位於:class scrapy.extensions.memdebug.
MemoryDebugger
調試內存使用的擴展。 它收集有關如下信息:
要啓用此擴展,請打開MEMDEBUG_ENABLED設置。 信息將被存儲在stats中。
9.4.5 Close spider extension
源碼位於:class scrapy.extensions.closespider.
CloseSpider
當知足一些條件時自動關閉蜘蛛,對每一個條件使用特定的關閉緣由。
關閉蜘蛛的條件能夠經過如下設置進行配置:
CLOSESPIDER_TIMEOUT
CLOSESPIDER_ITEMCOUNT
CLOSESPIDER_PAGECOUNT
CLOSESPIDER_ERRORCOUNT
默認是:
CLOSESPIDER_TIMEOUT = 0 CLOSESPIDER_PAGECOUNT = 0 CLOSESPIDER_ITEMCOUNT = 0 CLOSESPIDER_ERRORCOUNT = 0
9.4.5 StatsMailer extension
源碼位於:class scrapy.extensions.statsmailer.
StatsMailer
這個簡單的擴展能夠用來發送一個通知電子郵件,每當一個域名已經完成,包括Scrapy統計收集。 電子郵件將發送給STATSMAILER_RCPTS設置中指定的全部收件人。
9.4.6 Debugging extensions
堆棧跟蹤轉儲擴展Stack trace dump extension
源碼位於:class scrapy.extensions.debug.
StackTraceDump
9.4.7 Debugger extension
源碼位於:class scrapy.extensions.debug.
Debugger
在收到SIGUSR2信號時,在正在運行的Scrapy進程中調用Python調試器。 調試器退出後,Scrapy進程繼續正常運行。
此擴展只適用於POSIX兼容的平臺(即不是Windows)。
10.1.1 class scrapy.crawler.
Crawler
(spidercls, settings)
這個類必須實例化scrapy.spiders.Spider子類和scrapy.settings.Settings對象。經過from_crawler類方法傳遞給extension,訪問crawler對象的主要接口。
屬性包括:
self.extensions = ExtensionManager.from_crawler(self) self.settings.freeze() self.crawling = False self.spider = None self.engine = None self.signals = SignalManager(self) self.stats = load_object(self.settings['STATS_CLASS'])(self)
等等。
其中:
settings:
此抓取工具的設置管理器。
這被擴展和中間件用來訪問這個爬蟲的Scrapy設置。
有關Scrapy設置的介紹,請參閱上一篇博文。
有關API,請閱讀下文setting的接口。
signals:
這個爬蟲的信號管理器。
這是由擴展和中間件使用Scrapy功能。
有關信號的介紹,請參閱Signals。
有關API,請參閱下文的SignalManager類。
stats:
此抓取工具的統計信息收集器。
這用於擴展和中間件來記錄其行爲的統計信息,或訪問由其餘擴展收集的統計信息。
有關統計信息收集的介紹,請參閱統計信息收集。
有關API,請參閱下文StatsCollector類。
engine:
執行引擎,協調調度程序,下載程序和蜘蛛之間的核心爬行邏輯。
某些擴展可能須要訪問Scrapy引擎,以檢查或修改下載程序和調度程序的行爲,儘管這是一種高級用法,而且此API尚不穩定。
spider:
蜘蛛目前正在爬行。 這是構建爬網程序時提供的spider類的一個實例,它是在crawl()方法中給出的參數以後建立的。
crawl
(*args, **kwargs):
經過使用給定的args和kwargs參數實例化其spider類,啓動爬網程序,同時將執行引擎設置爲運動。
返回爬網完成時觸發的延遲。
10.1.2 class scrapy.crawler.
CrawlerRunner
(settings=None):
這是一個方便的助手類,能夠跟蹤,管理和運行已經設置好的Twisted反應堆內的抓取程序。
CrawlerRunner對象必須用一個Settings對象來實例化。
除非編寫手動處理爬網過程的腳本,不然不該該須要該類(由於Scrapy負責相應使用它)。 有關示例,請參閱從腳本運行Scrapy。
crawl
(crawler_or_spidercls, *args, **kwargs):
使用提供的參數運行爬網程序。
它會調用給定的Crawler的crawl()方法,同時跟蹤它,以便稍後中止。
若是crawler_or_spidercls不是Crawler實例,則此方法將嘗試使用此參數建立一個使用當前參數的spider類。
返回爬網完成時觸發的延遲。
Parameters: |
|
---|
crawlers:
創建一個 從crawl()
啓動的crawlers類,並管理這個類。
create_crawler
(crawler_or_spidercls):
返回一個 Crawler
對象
join
():
返回全部爬蟲執行完成後的延遲。
stop
():
同時中止全部正在進行的抓取工做。
當它們所有結束時,返回一個延遲
10.1.3 class scrapy.crawler.
CrawlerProcess
(settings=None):
基於上文提到的scrapy.crawler.CrawlerRunner類,
在一個進程中同時運行多個scrapy爬蟲的類。
這個類擴展了CrawlerRunner,增長了對啓動Twisted reactor和處理關閉信號的支持,好比鍵盤中斷命令Ctrl-C。 它還配置頂級日誌記錄。
若是你沒有在應用程序中運行另外一個Twisted reactor,這個工具應該比CrawlerRunner更好。
CrawlerProcess對象必須用一個Settings對象實例化。
除非編寫手動處理爬網過程的腳本,不然不該該須要該類(由於Scrapy負責相應使用它)。 有關示例,請參閱從腳本運行Scrapy。
函數基本與CrawlerRunner()類相同,但增長了start
(stop_after_crawl=True)函數,、
start
(stop_after_crawl=True):
此方法啓動Twisted reactor,將其池大小調整爲REACTOR_THREADPOOL_MAXSIZE,並根據DNSCACHE_ENABLED和DNSCACHE_SIZE安裝DNS緩存。
若是stop_after_crawl爲True,那麼使用join()將在全部爬蟲完成後中止反應堆。
參數:stop_after_crawl(boolean) - 當全部的抓取程序完成時,中止或禁止反應堆。
10.2 Settings API
10.2.1 scrapy.settings.
SETTINGS_PRIORITIES
源碼位於:scrapy.setting.__init__,py
默認值爲:
SETTINGS_PRIORITIES = { 'default': 0, 'command': 10, 'project': 20, 'spider': 30, 'cmdline': 40, }
設置Scrapy中使用的默認設置優先級的鍵名和優先級的字典。
每一個item定義一個設置入口點,給它一個用於識別的代碼名稱和一個整數優先級。優先值越大,在程序執行時優先級越高。
scrapy.settings.
get_settings_priority
(priority):
源碼位於:scrapy.__init__py
在SETTINGS_PRIORITIES字典中查找給定的字符串優先級並返回其數字值,或者直接返回給定的數字優先級。
class scrapy.settings.
Settings
(values=None, priority='project'):
源碼位於:scrapy.__init__py
是BaseSettings的子類。
此對象存儲Scrapy設置,用於配置內部組件,並可用於任何進一步的自定義。
它是一個直接的子類,支持BaseSettings的全部方法,另外,在實例化以後,實例化對象在scrapy中內置的設置將被填充到這個插件中(extension或middleware)。
class scrapy.settings.
BaseSettings
(values=None, priority='project'):
源碼位於:scrapy.__init__py
這個類的實例像字典同樣,可是存儲了它們的(鍵,值)對的優先級,而且能夠被凍結(即被標記爲不可變)。
在實例化的時候能夠經過attributes設置屬性,若是優先級是字符串的話,那麼將在SETTINGS_PRIORITIES中查找優先級名稱。 不然,應該提供一個特定的整數。
建立對象後,可使用set()方法加載或更新新設置,而且可使用字典的方括號表示法或實例的get()方法及其值轉換變體來訪問。 當請求存儲的key時,將檢索具備最高優先級的值。
copy
()方法:
進行當前設置的深層複製。
此方法返回Settings類的新實例,並使用相同的值和優先級填充。
對新對象的修改不會反映在原始設置上。
copy_to_dict
():
複製當前設置並轉換爲字典。
這個方法返回一個新的字典,其中填入了與當前設置相同的值和優先級。
對返回的字典的修改不會反映在原始設置上。
此方法可用於在Scrapy shell中打印設置。
freeze
():
禁用對當前設置的進一步更改。
調用此方法後,設置的當前狀態將變爲不可變。 嘗試經過set()方法及其變體更改值將不可能,並將被警告。
frozencopy
():、
copy()返回對象的freeze()方法的別稱(copy後的設置不能被改變)。
get
(name, default=None):
獲取設置值,不影響其原始類型。
Parameters:
getbool
(name, default=False):
獲取一個布爾值的設置值。
1,'1',True'和'True'返回True,0,'0',False,'False'和None返回False。
例如,使用此方法時,經過設置爲「0」的環境變量填充的設置將返回False。
Parameters:
getdict
(name, default=None):
獲取設置值做爲字典。 若是設置原始類型是一個字典,它的副本將被返回。 若是它是一個字符串,它將被評估爲一個JSON字典。 若是它是一個BaseSettings實例自己,它將被轉換爲一個字典,包含它全部的當前設置值,就像get()所返回的那樣,可是會丟失關於優先級和可變性的全部信息。
Parameters:
getfloat
(name, default=0.0):
獲取setting的值,以float的形式表示。
Parameters: |
|
---|
getint
(name, default=0):
以一個整數的形式獲取setting的值。
Parameters: |
|
---|
getlist
(name, default=None):
獲取設置值做爲列表。 若是設置原始類型是一個列表,它的副本將被返回。 若是它是一個字符串,它將被「,」拆分。
例如,使用此方法時,經過設置爲「one,two」的環境變量填充的設置將返回列表['one','two']。
Parameters:
getpriority
(name):
返回name的當前數字優先級值,若是給定name不存在,則返回None。
Parameters:name (string) – the setting name
getwithbase
(name):
獲取相似字典的設置和_BASE對應的組合。
Parameters: | name (string) – name of the dictionary-like setting |
---|
maxpriority
():
返回全部設置中出現的最高優先級的數值,若是沒有存儲設置,則返回來自SETTINGS_PRIORITIES的默認數值。
set
(name, value, priority='project'):
存儲具備給定優先級的鍵/值屬性。
在配置Crawler對象以前(經過configure()方法)調用set()填充設置,不然它們不會有任何影響。
Parameters: |
|
---|
setmodule
(module, priority='project'):
以一個模塊的方式存儲設置。
這是一個幫助函數,它爲每一個具備優先級的設置的模塊聲明一個大寫的全局變量,供set()f方法調用。
Parameters: |
|
---|
update
(values, priority='project'):
存儲具備給定優先級的鍵/值對。
這是一個幫助函數,它爲每一個具備提供的優先級的值項調用set()。
若是values是一個字符串,則假定它是JSON編碼的,而且先用json.loads()解析成字典。 若是它是一個BaseSettings實例,則將使用每一個按鍵優先級並忽略優先級參數。 這容許用單個命令插入/更新具備不一樣優先級的設置。
Parameters: |
|
---|
10.3 SpiderLoader API
class scrapy.loader.
SpiderLoader
源碼位於:scrapy.loader.__init__.py
這個類負責檢索和處理整個項目中定義的蜘蛛類。
能夠經過在SPIDER_LOADER_CLASS項目設置中指定它們的路徑來使用自定義蜘蛛加載器。 他們必須徹底實現scrapy.interfaces.ISpiderLoader接口來保證無誤的執行。
from_settings
(settings):
Scrapy使用這個類方法來建立類的一個實例。 這個方法由當前的項目的設置調用,它將SPIDER_MODULES設置的蜘蛛遞歸的調用。
Parameters:settings (Settings
instance) – project settings
load
(spider_name):
獲取給定名稱的蜘蛛類。 它會查看加載的名爲spider_name的蜘蛛類的蜘蛛,若是找不到,將引起一個KeyError。
Parameters:spider_name (str) – spider class name
list
():
獲取項目中可用蜘蛛的名稱。
find_by_request
(request):
列出能夠處理給定請求的蜘蛛的名字。 將嘗試匹配請求的網址與蜘蛛的域名。
Parameters:request (Request
instance) – queried request
10.4 Signals API
Scrapy普遍使用信號來通知特定事件發生的時間。 您能夠捕捉Scrapy項目中的一些信號(例如,使用擴展)來執行其餘任務或擴展。
class scrapy.signalmanager.
SignalManager
(sender=_Anonymous)
connect
(receiver, signal, **kwargs):
將接收器功能鏈接到信號。
該信號能夠是任何對象,Scrapy帶有一些預約義的信號,記錄在signals。
Parameters:
disconnect
(receiver, signal, **kwargs):
從信號中斷開接收器功能。 這與connect()方法有相反的做用,參數是相同的。
disconnect_all
(signal, **kwargs):
斷開因此的接收器
Parameters: | signal (object) – the signal to disconnect from |
---|
send_catch_log
(signal, **kwargs):
發送一個信號,捕捉異常並記錄下來。
關鍵字參數傳遞給信號處理程序(經過connect()方法鏈接)。
send_catch_log_deferred
(signal, **kwargs):
像send_catch_log(),但支持從信號處理程序返回延遲。
返回全部信號處理程序延遲後被觸發的延遲。 發送一個信號,捕捉異常並記錄下來。
關鍵字參數傳遞給信號處理程序(經過connect()方法鏈接)。
10.5 Stats Collector API
scrapy.statscollectors模塊下有幾個Stats Collector,它們都實現StatsCollector類定義的Stats Collector API(它們都是繼承的)。
class scrapy.statscollectors.
StatsCollector:
get_value(key,default = None)
返回給定統計鍵的值,若是不存在,則返回默認值。
get_stats()
從當前正在運行的蜘蛛獲取全部統計做爲字典。
set_value(key,value)
爲給定的統計信息鍵設置給定的值。
set_stats(stats)
用stats參數中傳遞的字典覆蓋當前的統計信息。
inc_value(key,count = 1,start = 0)
假定給定的起始值(未設置時),按給定的計數遞增給定統計密鑰的值。
max_value(key,value)
只有在同一個鍵的當前值小於值的狀況下,才能爲給定鍵設置給定值。若是給定鍵沒有當前值,則始終設置該值。
min_value(key,value)
只有當同一個鍵的當前值大於值時,才爲給定的鍵設定給定的值。若是給定鍵沒有當前值,則始終設置該值。
clear_stats()
清除全部統計信息。
如下方法不是統計信息收集API的一部分,而是在實現自定義統計信息收集器時使用:
open_spider(spider)
打開給定的蜘蛛的統計收集。
close_spider(spider)
關閉給定的蜘蛛。在此以後,不能訪問或收集更具體的統計數據。