爬蟲2.5-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,
}