1. 程式人生 > >Python爬蟲從入門到成妖之7-----Scrapy框架中Download Middleware用法

Python爬蟲從入門到成妖之7-----Scrapy框架中Download Middleware用法

例子 start col res urn 鉤子 exception 安裝 打印

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

技術分享圖片

編寫自己的下載器中間件

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

為了演示這裏的中間件的使用方法,這裏創建一個項目作為學習,這裏的項目是關於爬去 httpbin.org這個網站
scrapy startproject httpbintest

cd httpbintest
scrapy genspider example example.com

創建好後的目錄結構如下:

技術分享圖片

這裏我們先寫一個簡單的代理中間件來實現ip的偽裝
創建好爬蟲之後我們講httpbin.py中的parse方法改成:

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

然後通過命令行啟動爬蟲:scrapy crawl httpbin

技術分享圖片

在最下面我們可以看到"origin": "114.250.88.66"
我們在查看自己的ip:

技術分享圖片

而我們要做就是通過代理中間件來實現ip的偽裝,在middleares.py中寫如下的中間件類:

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:9743

所以直接設置為代理用,代理的地址為日本的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,然後加上代理後成功訪問了谷歌,這裏我的代理是日本的代理節點,所以訪問到的是日本的谷歌站

技術分享圖片

Python爬蟲從入門到成妖之7-----Scrapy框架中Download Middleware用法