下载中间件

位置

引擎和下载器之间

作用

批量拦截整个项目的所有请求和响应

拦截请求

  1. - User-Agent伪装:为每个请求设置不一样的User-Agent值(构建请求值)
  2. - 代理IP设置

拦截响应

  1. - 篡改响应数据、响应对象

Downloader Middlewares主要方法

  • **process_request(**_**request**_**, **_**spider**_**)**

参数:

  • request (Request 对象) – 处理的request
  • spider (Spider 对象) – 该request对应的spider

作用:拦截所有请求
调用时机:当每个request通过下载中间件时,该方法被调用。
返回值:

  • None:如果其返回 None ,Scrapy将继续处理该request,执行其他的中间件的相应方法,直到合适的下载器处理函数(download handler)被调用, 该request被执行(其response被下载)。
  • Request对象:如果其返回 Request 对象,Scrapy则停止调用 process_request方法并重新调度返回的request。
  • raise一个 IgnoreRequest 异常:如果其raise一个 IgnoreRequest 异常,则安装的下载中间件的 process_exception() 方法会被调用。如果没有任何一个方法处理该异常, 则request的errback(Request.errback)方法会被调用。
    • **process_response(**_**request**_**, **_**response**_**, **_**spider**_**)**

参数:

  • request (Request 对象) – response所对应的request
  • response (Response 对象) – 被处理的response
  • spider (Spider 对象) – response所对应的spider

作用:拦截所有响应
调用时机:当每个response通过下载中间件时,该方法被调用。
返回值:

  • Response对象:如果其返回一个 Response (可以与传入的response相同,也可以是全新的对象), 该response会被在链中的其他中间件的 process_response() 方法处理。
  • Request对象:如果其返回一个 Request 对象,则中间件链停止, 返回的request会被重新调度下载。处理类似于 process_request() 返回request所做的那样。
  • raise一个 IgnoreRequest 异常:如果其抛出一个 IgnoreRequest 异常,则调用request的errback(Request.errback)。
    • **process_exception(**_**request**_**, **_**exception**_**, **_**spider**_**)**

参数:

  • request (是 Request 对象) – 产生异常的request
  • exception (Exception 对象) – 抛出的异常
  • spider (Spider 对象) – request对应的spider

作用:处理下载器下载时出现的异常
调用时机:当下载处理器(download handler)或process_request()(下载中间件)抛出异常(包括 IgnoreRequest 异常)时, Scrapy调用该方法 。
返回值

  • None:如果其返回 None ,Scrapy将会继续处理该异常,接着调用已安装的其他中间件的 process_exception() 方法,直到所有中间件都被调用完毕,则调用默认的异常处理。
  • Response对象:如果其返回一个 Response 对象,则已安装的中间件链的 process_response() 方法被调用。Scrapy将不会调用任何其他中间件的 process_exception() 方法。
  • Request对象:如果其返回一个 Request 对象, 则返回的request将会被重新调用下载。这将停止中间件的 process_exception() 方法执行,就如返回一个response的那样。

    Downloader Middlewares使用示例:

    ```python

    User-Agent池

    user_agent_list = [ “Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 “ “(KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1”, “Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 “ “(KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11”, “Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6 “ “(KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6”, “Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.6 “ “(KHTML, like Gecko) Chrome/20.0.1090.0 Safari/536.6”, “Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.1 “ “(KHTML, like Gecko) Chrome/19.77.34.5 Safari/537.1”, “Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/536.5 “ ]

拦截所有请求

def process_request(self, request, spider):

  1. # UA伪装
  2. # 从useragent列表中随机取一个User-Agent
  3. request.headers['User-Agent'] = random.choice(self.user_agent_list)
  4. return None

拦截所有的响应

def process_response(self, request, response, spider):

  1. return response

可被选用的代理IP

PROXY_http = [ ‘153.180.102.104:80’, ‘195.208.131.189:56055’, ] PROXY_https = [ ‘120.83.49.90:9000’, ‘95.189.112.214:35508’, ]

拦截发生异常的请求

def process_exception(self, request, exception, spider):

  1. # 代理IP设置
  2. # 判断协议类型:http/https
  3. if request.url.split(':')[0] == 'http':
  4. request.meta['proxy'] = 'http://' + random.choice(self.PROXY_http)
  5. else:
  6. request.meta['proxy'] = 'https://' + random.choice(self.PROXY_https)
  7. return request # 将修正之后的请求对象交给 引擎,重新发起请求

```