摘要:关于scrapy中download middleware的用法

scrapy提供了两种中间件,下载中间件(Downloader Middleware)和Spider中间件(Spider Middleware),下载中间件位于引擎和下载器之前。当引擎将Request传递给下载器,Request会首先经过Downloader Middleware。当下载器将生成的Response传递给引擎过程的过程中,也会经过Downloader Middleware。

使用说明

在配置文件settings.py中的DOWNLOADER_MIDDLEWARES中配置键值对,键为要打开的中间件,值为数字,代表优先级,值越低,优先级越高。
scrapy还有一个内部自带的下载中间件DOWNLOADER_MIDDLEWARES_BASE(不可覆盖)。scrapy在启用时会结合DOWNLOADER_MIDDLEWARES_BASE和DOWNLOADER_MIDDLEWARES。若要取消scrapy内部自带的下载中间件,可在DOWNLOADER_MIDDLEWARES将对应的key的值设为None。

下面是DOWNLOADER_MIDDLEWARES_BASE变量:

DOWNLOADER_MIDDLEWARES_BASE = 
{
    'scrapy.downloadermiddlewares.robotstxt.RobotsTxtMiddleware': 100,
    'scrapy.downloadermiddlewares.httpauth.HttpAuthMiddleware': 300,
    'scrapy.downloadermiddlewares.downloadtimeout.DownloadTimeoutMiddleware': 350,
    'scrapy.downloadermiddlewares.defaultheaders.DefaultHeadersMiddleware': 400,
    'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware': 500,
    'scrapy.downloadermiddlewares.retry.RetryMiddleware': 550,
    'scrapy.downloadermiddlewares.ajaxcrawl.AjaxCrawlMiddleware': 560,
    'scrapy.downloadermiddlewares.redirect.MetaRefreshMiddleware': 580,
    'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware': 590,
    'scrapy.downloadermiddlewares.redirect.RedirectMiddleware': 600,
    'scrapy.downloadermiddlewares.cookies.CookiesMiddleware': 700,
    'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware': 750,
    'scrapy.downloadermiddlewares.stats.DownloaderStats': 850,
    'scrapy.downloadermiddlewares.httpcache.HttpCacheMiddleware': 900,
}
如果要禁止自带的HttpProxyMiddleware和UserAgentMiddleware,在seetings.py文件中设置
DOWNLOADER_MIDDLEWARES = {
    'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware':None,
    'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware':None,
}即可

download middleware的方法说明

process_request(request, spider)

参数说明:

  • request(Request对象) - 正在处理的请求
  • spider(Spider对象) - 该request对应的spider

返回值:
当每个Request对象经过下载中间件时会被调用,优先级越高的中间件,越先调用;该方法应该返回以下对象:None/Response对象/Request对象/抛出IgnoreRequest异常;

  • 返回None:scrapy会继续执行其他中间件相应的方法;
  • 返回Response对象:scrapy不会再调用其他中间件的process_request方法,也不会去发起下载,而是直接返回该Response对象;
  • 返回Request对象:scrapy不会再调用其他中间件的process_request()方法,而是将其放置调度器待调度下载;
  • 抛出IgnoreRequest异常:已安装中间件的process_exception()会被调用,如果它们没有捕获该异常,则Request.errback会被调用;如果再没被处理,它会被忽略,且不会写进日志。

process_response(request, response, spider)

参数说明:

  • request(Request对象) - 发起响应的请求
  • response(Response对象) - 正在处理的响应
  • spider(Spider对象) - 此响应所针对的蜘蛛

返回值:
当每个Response经过下载中间件会被调用,优先级越高的中间件,越晚被调用,与process_request()相反;该方法返回以下对象:Response对象/Request对象/抛出IgnoreRequest异常。

  • 返回Response对象:scrapy会继续调用其他中间件的process_response方法;
  • 返回Request对象:停止中间器调用,将其放置到调度器待调度下载;
  • 抛出IgnoreRequest异常:已安装中间件的process_exception()会被调用,如果它们没有捕获该异常,则Request.errback会被调用;如果再没被处理,它会被忽略,且不会写进日志。

process_exception(request, exception, spider)

参数说明:

  • request(是一个Request对象) - 生成异常的请求
  • exception(一个Exception对象) - 引发的异常
  • spider(Spider对象) - 此请求所针对的蜘蛛

返回值:
当process_exception()和process_request()抛出异常时会被调用,应该返回以下对象:None/Response对象/Request对象;

  • 如果返回None:scrapy会继续调用其他中间件的process_exception();
  • 如果返回Response对象:中间件链的process_response()开始启动,不会继续调用其他中间件的process_exception();
  • 如果返回Request对象:停止中间器的process_exception()方法调用,将其放置到调度器待调度下载。

from_crawler(cls, crawler)

返回值:
如果存在该函数,from_crawler会被调用使用crawler来创建中间器对象,必须返回一个中间器对象,通过这种方式,可以访问到crawler的所有核心部件,如settings、signals等。

代码

以下详细用法参考(本地没代理环境不能实验):
python3的爬虫笔记18——Download Middleware中的用法 - 简书

class ProxyMiddleware(object):
    logger = logging.getLogger(__name__)

    def process_request(self, request, spider):
        # self.logger.debug('Using Proxy')
        # request.meta['proxy'] = 'http://127.0.0.1:1080'
        # return None
        pass

    def process_response(self, request, response, spider):
        # response.status = 201
        # return response
        pass

    def process_exception(self, request, exception, spider):
        self.logger.debug('Get Exception')
        self.logger.debug('Try Second Time')
        request.meta['proxy'] = 'http://127.0.0.1:1080'
        return request