scrapy之下载器中间件(Download Middleware)

Scrapy内置的Download Middleware为Scrapy提供了基础的功能,每个Download Middleware都定义了一个或多个方法的类,核心的方法有三个:

  • process_request(request,spider)
  • process_response(request,response,spider)
  • process_exception(request,exception,spider)

1 process_request(request,spider)

  Request被 Scrapy 引擎调度给 Downloader 之前,process request()方法就会被调用,也就是在Request从队列里调度出来到 Downloader下载执行之前,我们都可以用 process request()方法对Request进行处理。方法的返回值必须为None、Response 对象、Request 对象之一,或者抛出IgnoreRequest 异常

request()方法的参数有如下两个。

  • request,是Request 对象,即被处理的Request。

  • spider,是Spdier 对象,即此 Request 对应的Spider。

 返回类型不同,产生的效果也不同。

(1)当返回是 None 时,Scrapy 将继续处理该 Request,接着执行其他 Downmloader Middleware 的process_request()方法,一直到Downloader把Request 执行后得到Response 才结束。这个过 程其实就是修改 Request 的过程,不同的Downloader Middleware按照设置的优先级顺序依次对Request进行修改,最后送至 Downloader执行。

(2)当返回为 Response 对象时,更低优先级的 Downloader Middleware 的 process_request()和process_exception()方法就不会被继续调用,每个 Downloader Middleware的process_response()方法转而被依次调用。调用完毕之后,直接将Response对象发送给Spider来处理。

(3)当返回为 Request 对象时,更低优先级的Downloader Middleware的 process_request()方法停止执行。这个 Request会重新放到调度队列里,其实它就是一个全新的Request.等待被调度。如果被 Scheduler调度了,那么所有的Downloader Middleware的 process_request()方法会被重新按照顺序执行。

(4)如果 IgnoreRequest 异常抛出,则所有的 Downloader Middleware 的 process_exception()方法会依次执行。如果没有一个方法处理这个异常,那么Request的errorback()方法就会回调。
如果该异常还没有被处理,那么它便会被忽略。

 2 process_response(request,response, spider)

Downloader执行 Request 下载之后,会得到对应的Response。Scrapy 引擎便会将Response发送给Spider(爬虫文件) 进行解析。在发送之前,我们都可以用process_response()方法来对Response进行处理。方的返回值必须为Request 对象、Response 对象之一,或者抛出 IgnoreRequest异常.

 process response()方法的参数有如下三个:

  • request,是 Request 对象,即此 Response对应的Request。
  • response,是 Response 对象,即此被处理的Response。
  • spider,是 Spider 对象,即此 Response对应的 Spider。

 不同的返回情况:

(1)当返回为 Request 对象时,更低优先级的 Downloader Midleware的 process_response()方法不会继续调用。该 Request 对象会重新放到调度队列里等待被调度,它和当于一个全新的Request。然后、该 Request 会被 process_request()方法顺次处理。

(2)当返回为 Response 对象时,更低优先级的 Downlonder Midleware 的process_response(),会继续调用、继续对该 Response 对象进行处理。

(3)如果IgnoreRequest异常抛出,则Request 的errorback()方法会回调。如果该异常还没有被处理、那么它便会被忽略。

3 process_exception(request,exception,spider)

当 Downlonder 或 process_request()方法抛出异常时,例如抛出 IgnoreRequest 异常rocess exception()方法就会被调用。方法的返回值必须为 None、Response对象、Request对象之一。

process_exception()方法的参数有如下三个:

  • request,是 Request对象,即产生异常的Request
  • exception,是Exception对象,即抛出的异常。
  • spdier,是 Spider对象,即Request对应的 Spider。

不同的返回情况:

(1)当返回为 None 时,更低优先级的Downloader Middleware 的 process_exception()会被继续顺次调用、直到所有的方法都被调度完毕

(2)当返回为Response对象时,更低优先级的Downloader Middleware 的 process_exception()方法不再被继续调用,每个 Downloader Middleware 的 process_response()方法转而被依次调用。

(3)当返回为Request对象时,更低优先级的Downloader Middleware 的 process_exception()也不再被继续调用,该 Request 对象会重新放到调度队列里面等待被调度,它相当于一个全新的Request。然后,该Request又会被 proces_request()方法顺次处理。

示例:用process_request来设置一个随机的user-agent

在middlewares.py中添加一个类:

# 用于设置随机user-agent
class RandomUserAgentMiddleware():
    def __init__(self):
        self.user_agents=[
            'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:74.0) Gecko/20100101 Firefox/74.0',
            'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36',
            'Mozilla/5.0 (Windows Phone 10.0; Android 6.0.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Mobile Safari/537.36 Edge/15.15063'
        ]
    
    def process_request(self,request,spider):
        request.headers['User-Agent']=random.choice(self.user_agents)

在settings.py中将DOWNLOADER_MIDDLEWARES取消注释并设置内容:

DOWNLOADER_MIDDLEWARES = {
   'scrapyseleniumtaobao.middlewares.RandomUserAgentMiddleware': 543,
}
原文地址:https://www.cnblogs.com/codexlx/p/12618073.html