Python之爬蟲(十九) Scrapy框架中Download Middleware用法

這篇文章中寫了經常使用的下載中間件的用法和例子。
Downloader Middleware處理的過程主要在調度器發送requests請求的時候以及網頁將response結果返回給spiders的時候,因此從這裏咱們能夠知道下載中間件是介於Scrapy的request/response處理的鉤子,用於修改Scrapy request和response。python

編寫本身的下載器中間件

編寫下載器中間件,須要定義如下一個或者多個方法的python類scrapy

爲了演示這裏的中間件的使用方法,這裏建立一個項目做爲學習,這裏的項目是關於爬去httpbin.org這個網站
scrapy startproject httpbintest 
cd httpbintest
scrapy genspider example example.com
ide

建立好後的目錄結構以下:函數

這裏咱們先寫一個簡單的代理中間件來實現ip的假裝
建立好爬蟲以後咱們講httpbin.py中的parse方法改爲:學習

    def parse(self, response):
        print(response.text)

而後經過命令行啓動爬蟲:scrapy crawl httpbin網站

在最下面咱們能夠看到"origin": "114.250.88.66"
咱們在查看本身的ip:google

 

 而咱們要作就是經過代理中間件來實現ip的假裝,在middleares.py中寫以下的中間件類:url

class ProxyMiddleare(object):
    logger = logging.getLogger(__name__)
    def process_request(self,request, spider):
        self.logger.debug("Using Proxy")
        request.meta['proxy'] = 'http://127.0.0.1:9743'
        return None

這裏由於我本地有一個代理FQ地址爲:http://127.0.0.1:9743spa

因此直接設置爲代理用,代理的地址爲日本的ip
而後在settings.py配置文件中開啓下載中間件的功能,默認是關閉的命令行

而後咱們再次啓動爬蟲:scrapy crawl httpbin
從下圖的輸入日誌中咱們能夠看書咱們定義的中間件已經啓動,而且輸入了咱們打印的日誌信息,而且咱們查看origin的ip地址也已經成了日本的ip地址,這樣咱們的代理中間件成功了

 

 

詳細說明

class Scrapy.downloadermiddleares.DownloaderMiddleware

process_request(request,spider)

當每一個request經過下載中間件時,該方法被調用,這裏有一個要求,該方法必須返回如下三種中的任意一種:None,返回一個Response對象,返回一個Request對象或raise IgnoreRequest。三種返回值的做用是不一樣的。

None:Scrapy將繼續處理該request,執行其餘的中間件的相應方法,直到合適的下載器處理函數(download handler)被調用,該request被執行(其response被下載)。

Response對象:Scrapy將不會調用任何其餘的process_request()或process_exception() 方法,或相應地下載函數;其將返回該response。 已安裝的中間件的 process_response() 方法則會在每一個response返回時被調用。

Request對象:Scrapy則中止調用 process_request方法並從新調度返回的request。當新返回的request被執行後, 相應地中間件鏈將會根據下載的response被調用。

raise一個IgnoreRequest異常:則安裝的下載中間件的 process_exception() 方法會被調用。若是沒有任何一個方法處理該異常, 則request的errback(Request.errback)方法會被調用。若是沒有代碼處理拋出的異常, 則該異常被忽略且不記錄。

process_response(request, response, spider)

process_response的返回值也是有三種:response對象,request對象,或者raise一個IgnoreRequest異常

若是其返回一個Response(能夠與傳入的response相同,也能夠是全新的對象), 該response會被在鏈中的其餘中間件的 process_response() 方法處理。

若是其返回一個 Request 對象,則中間件鏈中止, 返回的request會被從新調度下載。處理相似於 process_request() 返回request所作的那樣。

若是其拋出一個 IgnoreRequest 異常,則調用request的errback(Request.errback)。 若是沒有代碼處理拋出的異常,則該異常被忽略且不記錄(不一樣於其餘異常那樣)。

這裏咱們寫一個簡單的例子仍是上面的項目,咱們在中間件中繼續添加以下代碼:

 

而後在spider中打印狀態碼:

這樣當咱們從新運行爬蟲的時候就能夠看到以下內容

process_exception(request, exception, spider)

當下載處理器(download handler)或 process_request() (下載中間件)拋出異常(包括 IgnoreRequest 異常)時,Scrapy調用 process_exception()。

process_exception() 也是返回三者中的一個: 返回 None 、 一個 Response 對象、或者一個 Request 對象。

若是其返回 None ,Scrapy將會繼續處理該異常,接着調用已安裝的其餘中間件的 process_exception() 方法,直到全部中間件都被調用完畢,則調用默認的異常處理。

若是其返回一個 Response 對象,則已安裝的中間件鏈的 process_response() 方法被調用。Scrapy將不會調用任何其餘中間件的 process_exception() 方法。

若是其返回一個 Request 對象, 則返回的request將會被從新調用下載。這將中止中間件的 process_exception() 方法執行,就如返回一個response的那樣。 這個是很是有用的,就至關於若是咱們失敗了能夠在這裏進行一次失敗的重試,例如當咱們訪問一個網站出現由於頻繁爬取被封ip就能夠在這裏設置增長代理繼續訪問,咱們經過下面一個例子演示

scrapy genspider google www.google.com 這裏咱們建立一個谷歌的爬蟲,

而後啓動scrapy crawl google,能夠看到以下狀況:

這裏咱們就寫一箇中間件,當訪問失敗的時候增長代理
首先咱們把google.py代碼進行更改,這樣是白超時時間設置爲10秒要否則等待過久,這個就是咱們將spider裏的時候的講過的make_requests_from_url,這裏咱們把這個方法重寫,並將等待超時時間設置爲10s

這樣我從新啓動爬蟲:scrapy crawl google,能夠看到以下:

這裏若是咱們不想讓重試,能夠把重試中間件關掉:

這樣設置以後咱們就把失敗重試的中間件給關閉了,設置爲None就表示關閉這個中間件,從新啓動爬蟲咱們也能夠看出沒有進行重試直接報錯了

咱們將代理中間件的代理改爲以下,表示遇到異常的時候給請求加上代理,並返回request,這個樣就會從新請求谷歌

從新啓動谷歌爬蟲,咱們能夠看到,咱們第一次返回咱們打印的日誌信息GET Exception,而後加上代理後成功訪問了谷歌,這裏個人代理是日本的代理節點,因此訪問到的是日本的谷歌站

相關文章
相關標籤/搜索