爬蟲2.5-scrapy框架-下載中間件
目錄
- scrapy框架-下載中間件
scrapy框架-下載中間件
middlewares.py中有兩個類,一個是xxSpiderMiddleware類 一個是xxDownloaderMiddleware類,xx代表項目名,本次筆記主要記錄DownloaderMiddleware類的一些知識點
1. process_request(self, request, spider):
這個方法會在請求之前執行,所以可以添加代理pi和隨機請求頭等
1.1 參數:
? reuqest:發送的請求
? spider:發送請求的spider對象,即request是哪個爬蟲對象發過來的。
1.2 返回值:
1)如果返回的是None:scrapy將把request對象交給下一個中間件
2)如果返回的是response對象,則不會調用任何的process_request方法,而是將response對象直接返回給已激活的process_response()方法
3)返回request對象,不會調用下一個中間件,而是根據返回的request對象返回數據
4)拋出異常,調用process_exception方法。
2. process_response(self, request, response, spider):
2.1 參數:
1)request:之前發送的request請求對象
2)response:返回的數據對象
3)spider:爬蟲對象
2.2 返回值:
1)返回response對象,會將這個新的response對象傳給其他中間件,最終傳給爬蟲
2)返回request對象,下載器鏈被切斷,返回的request會重新被下載器調度
3)拋出異常,調用request中的errback方法,沒有就拋出異常
3. 設置請求頭
專業請求頭網站 http://www.useragentstring.com/pages/useragentstring.php?type=Browser
定義xxDownloaderMiddleware類,在寫process_request()方法
class xxDownloaderMiddleware(object): USER_AGENTS = [ ‘xxxx‘, ‘xxxxx‘, ‘xxxx‘, ‘xxxxxx‘ # 請求頭 ] def process_request(self, request, spider): user_agent = random.choice(self.USER_AGENTS) request.headers[‘user-agent‘] = user_agent
然後在settings.py中打開中間件設置
DOWNLOADER_MIDDLEWARES = {
‘projectname.middlewares.xxDownloaderMiddleware‘: 543
}
4. ip代理池
代理服務商:
快遞代理、芝麻代理、太陽代理、訊代理、螞蟻代理
當然是花錢買,免費的不好用
新建一個類
class XXXDownloaderMiddleware(object):
PROXIES = [‘IP1‘,‘IP2‘,‘IP3‘]
def process_request(self, request, spider):
proxy = random.choice(self.PROXIES)
request.meta(‘proxy‘) = proxy
修改settings.py
DOWNLOADER_MIDDLEWARES = {
‘project.middlewares.XXXDownloaderMiddleware‘:542 # 多個中間件的優先級自己設定,1為最高級
}
5. 一個略完善的代理思路
開啟兩個下載中間件,一個請求頭代理,一個ip代理,添加到settings中間
ip代理中間件需要兩個函數,
1 process_request(self, request, spider)
2 process_response(self, request, response, spider)
函數1 獲取代理ip、端口、過期時間可以調用代理網站給的api獲取
函數2 當ip被封,返回的是值是不一樣的,所以可以return request對象 重新分配代理ip、端口
偽代碼:
def process_request(self, request, spider):
if ‘proxy‘ not in request.meta or 代理即將過期 or 代理被封:
更新代理
更新代理被封標誌
request.meta[‘proxy‘] = 代理ip
def process_response(self, request, response, spider):
if response.status != 200 or 驗證碼頁面url特殊標誌 in response.url:
代理被封標誌
更新代理
return request
return response
因為scrapy框架下各個請求是異步的,所以更新代理的函數需要進行一定的更改,因為每次將一個ip使用到被封才使用下一個ip,所以每個異步請求都應該使用同一個ip,過期或被封之後才更換
def 更新代理:
加鎖:
if 代理沒有設置好 or 代理即將過期
請求代理ip
6. selenium+chromedriver中間件
這個中間件相當於使用chromedriver訪問頁面,並將各類ajax數據傳回給爬蟲進行解析,而scrapy框架負責調度url和數據解析存儲。
當頁面中ajax數據較多且復雜時,采用這種方式更方便。
~ meddlewares.py
from selenium import webdriver
from scrapy.http.response.html import HtmlResponse
class SeleniumDownloaderMiddleware(object):
def __init__(self):
self.driver = webdriver.Chrome(executable_path=r‘D:\chromedriver\chromedriver.exe‘) # 創建driver
def process_request(self, request, spider):
self.driver.get(request.url) # 打開不同的頁面
source = self.driver.page_source
response = HtmlResponse(self.driver.current_url, body=source, request=request, encoding=‘utf-8‘) # 傳入的參數是按原本response對象需要的參數
return response # 必須返回response對象給爬蟲
最後在settings.py中開啟這個中間件
DOWNLOADER_MIDDLEWARES = {
‘boss.middlewares.SeleniumDownloaderMiddleware‘: 543,
}
爬蟲2.5-scrapy框架-下載中間件