DownloaderMiddleware:下载中间件。它是处于scrapy的Request和Response之间的处理模块。
- 流程:
Scheduler 从队列中拿出一个Request发送给Downloader执行下载,这个过程会经过DownloaderMiddleware的处理,另外,当Downloader将Response返回给Spider时会再次经过DownloadederMiddleware处理。
也就是说,DownloaderMiddleware在整个架构中起作用的位置是以下两个。
- 在Scheduler调度出队列的Request发送给下载器下载之前,我们可以在Request被执行下载之前对其进行修改。
- 在下载器下载完成发送给Spider之前,我们可以在Response被Spider解析之前对其进行修改。
下载中间件的功能十分强大,修改User-Agent、处理重定向、设置代理、失败重试、设置Cookies等功能都需要借助它完成
使用说明
Scrapy已经提供了许多下载中间件,比如失败重试,自动重定向等。它们被DOWNLOADER_MIDDLEWARE_BASE变量所定义。
这是一个字典,键名为下载中间件的名称,键值代表了调用的优先级,数字越小代表越靠近Scrapy引擎,越大越靠近Downloader。
每个下载中间件都可以定义 process_request() 方法和 process_response() 方法来分别处理请求和响应。对于process_request()方法来说,优先级数字越小越先被调用,对于process_response() 方法来说,优先级数字越大越先被调用。
如果自己定义的下载中间件要添加到项目里,DOWNLOADER_MIDDLEWARE_BASE变量不能直接修改,Scrapy提供了另外一个设置变量DOWNLOADER_MIDDLEWARES,我们直接修改这个变量就可以添加自己定义的下载中间件,以及禁用DOWNLOADER_MIDDLEWARE_BASE里面定义的DOWNLOADER_MIDDLEWARE。
核心方法
核心方法有如下三个:
- process_request(request, spider).
- process_response(request,response,spider)
- process_exception(request,exception,spider)
我们只需要实现至少一个方法就可以定义一个下载中间件。
方法详解
process_request(request,spider)
在 Request被Scrapy引擎调度给下载器之前,我们可以使用此方法对Request进行处理。方法的返回值必须为 None、Response对象或者Request对象,或者抛出IgnoreRequest异常
参数:
1.request:Request对象,即被处理的Request。
2.spider: Spider对象,即此Request对应的Spider。
- 当返回是None时,正常执行,这个过程就是修改Request的过程。
- 当返回为Response对象时,更低优先级的下载中间件的process_request()方法和process_exception()方法就不i会被继续调用,每个下载中间件的process_response()方法被依次调用,调用完毕之后,直接将Response对象发送给Spider处理。
- 当返回为Request对象时,更低优先级的下载中间件的process_request()方法会停止执行,这个Request会被重新方到调度队列里等待调用,如果被Scheduler调度了,那么所有的下载中间件的process_request()方法会被重新按照顺序执行。
- 当抛出异常时,则所有的下载中间件的process_exception()方法会依次执行。如果没有一个方法处理这个异常,那么Request的erroback()方法就会回调,还没有处理该异常的方法,那么它就会被忽略。
process_response(request,response,spider)
在下载器执行下载之后,会得到Response,在引擎将Response发送给Spider解析之前,我们可以使用此方法对Response进行处理。方法的返回值必须为 Response对象或者Request对象,或者抛出IgnoreRequest异常
参数:
1.request:Request对象,即此Response对应的Request
2.response:Response对象,即此被处理的Response
3.spider:Spider对象,即此Response对应的Spider
- 当返回为Request对象时,更低优先级的下载中间件的process_response()方法不会继续调用,该Request对象被重新放入调度队列等待调度。然后该Request会被process_request()方法顺次处理。
- 当返回为Response对象时,更低优先级的下载中间件的process_response()方法会继续调用,继续对该Response进行处理。
- 当返回异常时,同上。