Scrapy 中间件
Downloader Middleware 的用法
Downloader Middleware 即下载中间件,它是处于Scrapy 的Request 和Response之间的处理模块。
Downloader Middleware 在整个架构中起作用的位置是以下两个:
- 在Scheduler 调度出队列的Request 发送给Doanloader 下载之前,也就是我们可以在Request执行下载之前对其进行修改。
- 在下载后生成的Response 发送给Spider 之前,也就是我们可以在生成Resposne 被Spider 解析之前对其进行修改。
利用Downloader Middleware 可以修改User-Agent 、处理重定向、设置代理、失败重试、设置Cookies等
下载中间件,爬虫中间件都是写在middlewares.py中(名字随便命名)的,在settings.py中配置生效,如下
# 数字小的Downloader Middleware 会被优先调用
# 爬虫中间件
SPIDER_MIDDLEWARES = { 'cnblogs_crawl.middlewares.CnblogsCrawlSpiderMiddleware': 543, }
# 下载中间件 DOWNLOADER_MIDDLEWARES = { 'cnblogs_crawl.middlewares.CnblogsCrawlDownloaderMiddleware': 543, }
Downloader Middleware中间件三个方法
process _request(self, request, spider):
该方法被Scrapy引擎调度给Downloader之前调用
# - return None: Scrapy将继续处理该Request,接着执行其他Downloader Middleware的其他中间件的process_request()方法,一直到Downloader把Request执行后得到Response才结束。 # - return Response:更低优先级的Downloader Middleware 的process_request()和process_exception()方法就不会被继续调用,
每个Downloader Middleware的process response()方法转而被依次调用。
调用完毕之后,直接将Response对象发送给Spider来处理。(可以自己爬,包装成Response) # - return Request : 相当于把Request重新给了引擎,引擎再去做调度 # - 抛异常:执行process_exception
process_response(self, request, response, spider):
Downloader执行Request下载之后,会得到对应的Response 。Scrapy引擎便会将Response 发送给Spider进行解析。在发送之前,我们都可以用process_response()方法来对Response 进行处理。
# - return Response :继续处理当次Response,继续走更低优先级的中间件 # - return Request :重新给引擎做调度 # - or raise IgnoreRequest :process_exception
process_exception(self, request, exception, spider):
当Downloader 或process_request()方法抛异常时,例如抛出Ignore Request异常,process_exception()方法就会被调用
# - return None: 更低优先级的Downloader Middleware的process_exception()会被继续顺次调用,直到所有的方法都被调度完毕 # - return Response: 后续中间件的process_exception()方法不再被继续调用,每个Downloader Middleware 的process_response()方法转而被依次调用。 # - return Request:更低优先级的Downloader Middleware的process_exception()不再被继续调用,该Resquest给引擎(重新调度)
案例:process _request中加cookie、代理和User-Agent
class CnblogsCrawlDownloaderMiddleware(object): # 获取代理函数 def get_proxy(self): import requests proxy = requests.get('代理地址/get').json()['proxy'] return proxy def process_request(self, request, spider): # 1 加cookie(在request.cookies中就是访问该网站的cookie) print(request.cookies) #从你的cookie池中取出来的, 字典,设置 request.cookies={'k':'v'} print(request.cookies) # 2 加代理 在request.meta['proxy']中加 request.meta['proxy'] = self.get_proxy() # 3 修改useragent from fake_useragent import UserAgent ua = UserAgent(verify_ssl=False) request.headers['User-Agent'] = ua return None