設置下載中間件(Downloader Middlewares)
下載中間件是處於引擎(crawler.engine)和下載器(crawler.engine.download())之間的一層組件,可以有多個下載中間件被加載運行。
-
當引擎傳遞請求給下載器的過程中,下載中間件可以對請求進行處理 (例如增加http header信息,增加proxy信息等);
-
在下載器完成http請求,傳遞響應給引擎的過程中, 下載中間件可以對響應進行處理(例如進行gzip的解壓等)
要激活下載器中間件組件,將其加入到 DOWNLOADER_MIDDLEWARES 設置中。 該設置是一個字典(dict),鍵為中間件類的路徑,值為其中間件的順序(order)。
DOWNLOADER_MIDDLEWARES = { 'mySpider.middlewares.MyDownloaderMiddleware': 543, }
編寫下載器中間件十分簡單。每個中間件組件是一個定義了以下一個或多個方法的Python類:
class scrapy.contrib.downloadermiddleware.DownloaderMiddleware
process_request(self, request, spider)
-
當每個request通過下載中間件時,該方法被調用。
-
process_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)方法會被調用。如果沒有代碼處理拋出的異常, 則該異常被忽略且不記錄(不同於其他異常那樣)。
-
-
參數:
request (Request 對象)
– 處理的requestspider (Spider 對象)
– 該request對應的spider
process_response(self, request, response, spider)
當下載器完成http請求,傳遞響應給引擎的時候調用
-
process_request() 必須返回以下其中之一: 返回一個 Response 對象、 返回一個 Request 對象或raise一個 IgnoreRequest 異常。
-
如果其返回一個 Response (可以與傳入的response相同,也可以是全新的對象), 該response會被在鏈中的其他中間件的 process_response() 方法處理。
-
如果其返回一個 Request 對象,則中間件鏈停止, 返回的request會被重新調度下載。處理類似於 process_request() 返回request所做的那樣。
-
如果其拋出一個 IgnoreRequest 異常,則調用request的errback(Request.errback)。 如果沒有代碼處理拋出的異常,則該異常被忽略且不記錄(不同於其他異常那樣)。
-
-
參數:
request (Request 對象)
– response所對應的requestresponse (Response 對象)
– 被處理的responsespider (Spider 對象)
– response所對應的spider
實例
#!/usr/bin/env python # -*- coding:utf-8 -*- import random import base64 from settings import USER_AGENTS from settings import PROXIES # 隨機的User-Agent class RandomUserAgent(object): def process_request(self, request, spider): useragent = random.choice(USER_AGENTS) request.headers.setdefault("User-Agent", useragent) class RandomProxy(object): def process_request(self, request, spider): proxy = random.choice(PROXIES) if proxy['user_passwd'] is None: # 沒有代理賬戶驗證的代理使用方式 request.meta['proxy'] = "http://" + proxy['ip_port'] else: # 對賬戶密碼進行base64編碼轉換 base64_userpasswd = base64.b64encode(proxy['user_passwd']) # 對應到代理服務器的信令格式里 request.headers['Proxy-Authorization'] = 'Basic ' + base64_userpasswd request.meta['proxy'] = "http://" + proxy['ip_port']
為什么HTTP代理要使用base64編碼:
HTTP代理的原理很簡單,就是通過HTTP協議與代理服務器建立連接,協議信令中包含要連接到的遠程主機的IP和端口號,如果有需要身份驗證的話還需要加上授權信息,服務器收到信令后首先進行身份驗證,通過后便與遠程主機建立連接,連接成功之后會返回給客戶端200,表示驗證通過,就這么簡單,下面是具體的信令格式:
修改settings.py配置USER_AGENTS和PROXIES
添加USER_AGENTS:
USER_AGENTS = [ "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 2.0.50727; Media Center PC 6.0)", "Mozilla/5.0 (X11; U; Linux; en-US) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3) Arora/0.6", "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9) Gecko/20080705 Firefox/3.0 Kapiko/3.0", ]
添加代理IP設置PROXIES:
PROXIES = [ {'ip_port': 'ip:port1', 'user_passwd': 'user1:pass1'}, {'ip_port': 'ip2:port2', 'user_passwd': 'user2:pass2'}, {'ip_port': 'ip3:port3', 'user_passwd': 'user3:pass3'}, ]
除非特殊需要,禁用cookies,防止某些網站根據Cookie來封鎖爬蟲。
COOKIES_ENABLED = False
設置下載延遲
DOWNLOAD_DELAY = 3
最后添加自己寫的下載中間件類
DOWNLOADER_MIDDLEWARES = { 'mySpider.middlewares.MyDownloaderMiddleware': 543, }

BOT_NAME 默認: 'scrapybot' 當您使用 startproject 命令創建項目時其也被自動賦值。 CONCURRENT_ITEMS 默認: 100 Item Processor(即 Item Pipeline) 同時處理(每個response的)item的最大值。 CONCURRENT_REQUESTS 默認: 16 Scrapy downloader 並發請求(concurrent requests)的最大值。 DEFAULT_REQUEST_HEADERS 默認: 如下 { 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'Accept-Language': 'en', } Scrapy HTTP Request使用的默認header。 DEPTH_LIMIT 默認: 0 爬取網站最大允許的深度(depth)值。如果為0,則沒有限制。 DOWNLOAD_DELAY 默認: 0 下載器在下載同一個網站下一個頁面前需要等待的時間。該選項可以用來限制爬取速度, 減輕服務器壓力。同時也支持小數: DOWNLOAD_DELAY = 0.25 # 250 ms of delay 默認情況下,Scrapy在兩個請求間不等待一個固定的值, 而是使用0.5到1.5之間的一個隨機值 * DOWNLOAD_DELAY 的結果作為等待間隔。 DOWNLOAD_TIMEOUT 默認: 180 下載器超時時間(單位: 秒)。 ITEM_PIPELINES 默認: {} 保存項目中啟用的pipeline及其順序的字典。該字典默認為空,值(value)任意,不過值(value)習慣設置在0-1000范圍內,值越小優先級越高。 ITEM_PIPELINES = { 'mySpider.pipelines.SomethingPipeline': 300, 'mySpider.pipelines.ItcastJsonPipeline': 800, } LOG_ENABLED 默認: True 是否啟用logging。 LOG_ENCODING 默認: 'utf-8' logging使用的編碼。 LOG_LEVEL 默認: 'DEBUG' log的最低級別。可選的級別有: CRITICAL、 ERROR、WARNING、INFO、DEBUG 。 USER_AGENT 默認: "Scrapy/VERSION (+http://scrapy.org)" 爬取的默認User-Agent,除非被覆蓋。 PROXIES: 代理設置 示例: PROXIES = [ {'ip_port': '111.11.228.75:80', 'password': ''}, {'ip_port': '120.198.243.22:80', 'password': ''}, {'ip_port': '111.8.60.9:8123', 'password': ''}, {'ip_port': '101.71.27.120:80', 'password': ''}, {'ip_port': '122.96.59.104:80', 'password': ''}, {'ip_port': '122.224.249.122:8088', 'password':''}, ] COOKIES_ENABLED = False 禁用Cookies