DownloaderMiddleware:下载中间件有三个重要方法:
process_request()、process_response()、process_exception()
实现其中任意一个方法即可定义一个Downloader
(一)process_request(self,request, spider)用法:
1、触发条件:request在被scrapy引擎调度给Downloader之前,该方法会被调用
2、方法的参数:1)request:当前被处理的request对象
2)spider:当前request对应的spider对象
3、方法的返回值:有以下4种
1)返回值为None:scrapy将继续处理该request,然后接着被用于其他DownloaderMiddleware中的process_request()
方法,知道DownloaderMiddleware把这个request执行后得到response对象时,才会结束这个request,(其本质
是修改request的过程,不同的DownloaderMiddleware按照设置的优先级顺序依次处理request,最后送到Downloader
中执行(不同DownloaderMiddleware的优先级在settings中的DOWNLOADER_MIDDLEWARES设置,数字值越小,优先级越高)
2)返回值为response对象:若返回值为response对象,则其他更低优先级(值更大)的DownloaderMiddleware中的
process_request()与process_exception()方法都不会被继续调用,而是调用他们每个DownloaderMiddleware中的
process_response()方法,调用完之后会将response对象发送给guazi.py中的处理方法进行解析
3)返回值为request对象:若返回值为request对象,则更低优先级的DownloaderMiddleware中的process_request()方法
会停止执行,这个request对象会被重新放入到调度队列,(即一个全新的request,会等待会调度)
4)若返回值为抛出一个异常,则所有的DownloaderMiddleware中的process_exception()方法会被依次执行,
若没有方法去处理这个异常,则会被发送请求的errback()(yield scrapy.Request(...,errback=方法名,...))方法回调,
若还是不能处理该异常,则会被忽略
(二)process_response(self, request, response, spider):
1、触发条件:当下载器Downloader返回response到spider时,该方法会被调用
2、方法的参数:1)request:当前response对应的request对象
2)response:当前response对象
3)spider:当前response对应的spider对象
3、方法的返回值:有以下3种
1)返回值为request对象:则更低优先级的DownloaderMiddleware中的process_response()方法不会被继续调用,
request对象会被放入到调度队列中等待调度
2)返回值为response对象:则更低优先级的DownloaderMiddleware中的process_response()方法会被依次继续调用,
接着来处理response对象
3)若抛出异常:则不会进入process_exception()方法中,而是直接被发送请求的errback()方法
(yield scrapy.Request(...,errback=方法名,...))回调,
(三)process_exception(self, request, exception, spider):
1、触发条件:当Downloader或者process_request()发生异常,例如抛出IgnoreRequest异常时,该方法会被调用
2、方法的参数:1)request:当前exception对应的request对象
2)exception:当前exception对象
3)spider:当前exception对应的spider对象
3、方法的返回值:有以下3种
1)返回值为None:则更低优先级的DownloaderMiddleware中的process_exception()方法会被调用,
2)返回值为response对象:则更低优先级的process_exception()方法不再被调用,
并且每个DownloaderMiddleware中的process_response()方法会按照优先级顺序被依次调用
3)返回值为request对象:则更低优先级的process_exception()方法不再被调用,
这是request对象会被放入到调度器中等待被调用
总结:理一下思路
1)当发送请求时,request经过ScrapyEngine引擎到Scheduler调度器,经过DownloaderMiddlewares下载中间件,
2)到Downloader下载器,response数据返回后,再经过DownloaderMiddlewares下载中间件,
3)根据response的不同结果执行后续操作,也就是上面的几种情况,
4)若response返回数据正常,则response对象,经过ScrapyEngine将数据发送至Spider进行后续解析,可以在guazi.py中定义各种数据处理方法
这样:request与response正常与否的情况都得到了妥善处理,完成了通信。