Downloader Middleware
Downloader Middleware就是下载中间件,下载中间件是处于引擎(crawler.engine)和下载器(crawler.engine.download())之间的一层组件,可以有多个下载中间件被加载运行。
- 当引擎传递请求给下载器的过程中,下载中间件可以对请求进行处理 (例如增加http header信息,增加proxy信息等);
- 在下载器完成http请求,传递响应给引擎的过程中, 下载中间件可以对响应进行处理(例如进行gzip的解压等)
Downloader Middleware的功能十分强大,修改User-Agent、处理重定向、设置代理、失败重试、设置Cookies等功能都需要借助它来实现。
使用说明
其实Scrapy已经提供许多Downloader Middleware,比如负责失败重试、自动重定向等功能的Middleware,它们在default_settings.py文件中被DOWNLOADER_MIDDLEWARES_BASE变量所定义。
1 | DOWNLOADER_MIDDLEWARES_BASE = { |
需要注意的是这个字典当中的键值是代表了调用的优先级,越小代表越靠近Scrapy引擎,数字越大越靠近Downloader,越小越先调用。
如果我们自己定义下载中间件要添加到项目中,要激活下载器中间件组件,将其加入到 DOWNLOADER_MIDDLEWARES 设置中。
1 | DOWNLOADER_MIDDLEWARES = { |
核心方法
每个中间件组件是一个定义了以下一个或多个方法的Python类 ,核的方法有下面三个:
1 | process_request(request, spider) |
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
process_exception(self, request, exception, spider)
- 当Downloader或process_request()方法抛出异常时被调用
- process_exception() 必须返回以下其中之一:None、Response对象、Request对象。
- 如果返回None时,更低优先级的Downloader Middleware的process_exception()方法会被继续调用,直到所有的方法都被调用完毕。
- 如果返回为Response对象时,更低优先级的Downloader Middleware的process_exception()方法不再被继续调用,每个Downloader Middleware的 process_response()方法转而被依次调用。
- 如果返回为Request对象时,更低优先级的Downloader Middleware的process_exception()方法不再被继续调用,该 Request 对象会重新放到调度队列里面等待被调度,它相当于一个全新的 Request 。
使用案例
Scrapy代理IP、Uesr-Agent的切换都是通过DOWNLOADER_MIDDLEWARES
进行控制,我们在settings.py
同级目录下创建middlewares.py
文件,包装所有请求 。
1 | import logging |