【Scrapy 框架】「版本2.4.0源码」Downloader 中间件(Downloader Middleware)详解篇

全部源码解析文章索引目录传送门

【Scrapy 框架】版本 2.4.0 源码篇:全部配置目录索引

内容介绍

下载器中间件是一个挂钩Scrapy的请求/响应处理的框架。这是一个轻量级的低级系统,用于全局更改Scrapy的请求和响应。
主要作用:

  1. 在Scrapy将请求发送到网站之前修改,处理请求,如:更换代理ip,header等。
  2. 在将响应传递给引擎之前处理收到的响应,如:响应失败重新请求,或将失败的做一定处理再返回给引擎。
  3. 忽略一些响应或者请求。

激活下载器中间件

要激活下载程序中间件组件,请将其添加到DOWNLOADER_MIDDLEWARES设置中,这是一个dict,其键为中间件类路径,其值为中间件顺序。

DOWNLOADER_MIDDLEWARES = {
    
    
    'myproject.middlewares.CustomDownloaderMiddleware': 543,
    'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware': None, # 禁用状态
}

全部中间件设置

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,
}

自定义下载器中间件

class scrapy.downloadermiddlewares.DownloaderMiddleware

process_request(request, spider)

process_request 函数是中间件在收到 request 请求之后执行的函数,该函数的执行顺序是按照 settings.py 中中间件的配置顺序执行的,如果该函数返回 None,继续执行后面的中间件的 process_request 方法,如果该函数返回 response,则不再继续执行后面的中间件的 process_request 方法。

参数:

  • request(Request 对象)–处理的request
  • spider(Spider 对象)–该request对应的spider
def process_request(self, request, spider):
        # Called for each request that goes through the downloader
        # middleware.
        # 每个交给下载器的request对象都会经过该方法,并期望返回response

        # Must either:
        # 如果该方法返回的是None,则继续执行其他下载中间件的process_request方法送往下载器,直到合适的下载器函数被调用,该request被执行,返回response
        # - return None: continue processing this request
        # 如果该方法返回的是response,则终止当前流程,也终止继续调用其他process_request方法,将该response通过引擎返回给爬虫
        # - or return a Response object
        # 如果该方法返回的是request,则终止当前流程,也终止继续调用其他process_request方法,将request返回给调度器,大多数情况是更换新的request请求
        # - or return a Request object
        # 抛出IgnoreRequest异常, 该异常就会交个process_exception方法进行处理; 如果没有任何一个方法处理该异常
        # 那么该请求就直接被忽略了, 也不会记录错误日志.
        # - or raise IgnoreRequest: process_exception() methods of
        #   installed downloader middleware will be called
        return None

process_response(request, response, spider)

process_response 函数是执行完 views.py 后执行的函数,process_response 函数有两个参数,一个是 request,一个是 response,response 是视图函数返回的响应对象,process_response 函数的返回值必须是 HttpResponse 对象。

参数:

  • request (Request 对象) – response所对应的request
  • response (Response 对象) – 被处理的response
  • spider (Spider 对象) – response所对应的spider
def process_response(self, request, response, spider):
    # Called with the response returned from the downloader.
    # 当下载器完成http请求,返回响应给引擎的时候调用

    # Must either;
    # 如果返回response,则继续执行,其他下载中间件也会处理该response,直至交给引擎再交给爬虫
    # - return a Response object
    # 如果返回request,则中间件终止,该request返回引擎再给调度器
    # - return a Request object
    # 抛出 IgnoreRequest 异常; 该请求就被忽略了且不做记录
    # - or raise IgnoreRequest
    return response

process_exception(request, exception, spider)

process_exception(self, request, exception) 函数有两个参数,exception 是视图函数异常产生的 Exception 对象,process_exception 函数的执行顺序是按照 settings.py 中设置的中间件的顺序的倒序执行,process_exception 函数只在视图函数中出现异常的时候才执行,它返回的值可以是 None,也可以是一个 HttpResponse 对象,如果返回 None,则继续由下一个中间件的 process_exception 方法来处理异常,如果返回 HttpResponse,将调用中间件中的 process_response 方法。

参数:

  • request (是 Request 对象) – 产生异常的request
  • exception (Exception 对象) – 抛出的异常
  • spider (Spider 对象) – request对应的spider
def process_exception(self, request, exception, spider):
    # Called when a download handler or a process_request()
    # 在下载处理程序或process_request()时调用
    # (from other downloader middleware) raises an exception.
	# (来自其他下载器中间件)引发异常
	
    # Must either:
    # - return None: continue processing this exception
    # -返回None:继续处理此异常
    # - return a Response object: stops process_exception() chain
    # -返回一个Response对象:停止process_exception()链
    # - return a Request object: stops process_exception() chain
    # -返回一个Request对象:停止process_exception()链
    pass

from_crawler(cls, crawler)

用于根据传入的参数和 crawler 对象来生成 scheduler,使得scheduler有crawler的属性和配置。

参数:

  • crawler(Crawlerobject)- 使用此中间件的爬网程序
    @classmethod
    def from_crawler(cls, crawler):
        # Scrapy使用此方法创建Spider。
        s = cls()
        crawler.signals.connect(s.spider_opened, signal=signals.spider_opened)
        return s

内置下载器中间件参数参考

CookiesMiddleware(Cookies中间件)

用来应对需要使用cookie的站点。

class scrapy.downloadermiddlewares.cookies.CookiesMiddleware

支持 cookiejar 会话传递

def parse(self, response):
    ......
    return scrapy.Request("http://www.example.com/otherpage",
        meta={
    
    'cookiejar': response.meta['cookiejar']},
        callback=self.parse_other_page)

settings中配置参数

COOKIES_ENABLED = True # 是否启用Cookies中间件。
COOKIES_DEBUG = True # Scrapy将记录请求中发送的所有cookie

DefaultHeadersMiddleware(默认请求头中间件)

,指定的所有默认请求标头,建议自定义随机请求头。

class scrapy.downloadermiddlewares.defaultheaders.DefaultHeadersMiddleware

settings中配置参数

DEFAULT_REQUEST_HEADERS = {
    
    
  'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
  'Accept-Language': 'en',
}

DownloadTimeoutMiddleware(下载超时中间件)

控制抓取数据超时的设置。

class scrapy.downloadermiddlewares.downloadtimeout.DownloadTimeoutMiddleware

settings中配置参数

DOWNLOAD_TIMEOUT = 1

spider中配置参数

download_timeout = 1

HttpAuthMiddleware(HTTP身份验证中间件)

对从某些spider生成的所有请求进行身份验证,比如token验证。

class scrapy.downloadermiddlewares.httpauth.HttpAuthMiddleware
from scrapy.spiders import CrawlSpider

class SomeIntranetSiteSpider(CrawlSpider):

    http_user = 'root'
    http_pass = 'password'
    token = 'xxxxxxxxxxxxxxxxxx'
   .......

HttpCacheMiddleware (缓存中间件)

为所有HTTP请求和响应提供了低级缓存。必须与缓存存储后端以及缓存策略结合使用。

class scrapy.downloadermiddlewares.httpcache.HttpCacheMiddleware

settings中配置参数

HTTPCACHE_ENABLED = True  # 是否启用HTTP缓存。
HTTPCACHE_EXPIRATION_SECS = 0 # 缓存的请求的到期时间,以秒为单位。
HTTPCACHE_DIR = 'httpcache' # 用于存储(低级)HTTP缓存的目录。空为将禁用HTTP缓存。
HTTPCACHE_IGNORE_HTTP_CODES = [] # 不要使用这些HTTP代码缓存响应。
HTTPCACHE_IGNORE_MISSING = True # 缓存中找不到的请求将被忽略,默认False。
HTTPCACHE_IGNORE_SCHEMES = ['file'] # 不使用这些URI方案缓存响应。
HTTPCACHE_STORAGE = 'scrapy.extensions.httpcache.FilesystemCacheStorage'
HTTPCACHE_DBM_MODULE = 'dbm' # 在DBM存储后端中使用的数据库模块。此设置特定于DBM后端。
HTTPCACHE_POLICY = 'scrapy.extensions.httpcache.DummyPolicy' # 实现缓存策略的类。
HTTPCACHE_GZIP = True # 使用gzip压缩所有缓存的数据,默认False。
HTTPCACHE_ALWAYS_STORE = True # 无条件缓存页面,默认False。
HTTPCACHE_IGNORE_RESPONSE_CACHE_CONTROLS = [] # 响应中的Cache-Control指令列表将被忽略。

缓存策略:

  1. Dummy policy(虚拟策略-默认)
    发现相同请求立即响应,且不从internet传入内容
class scrapy.extensions.httpcache.DummyPolicy
  1. RFC2616策略
    用于生产并在连续运行中使用,以节省带宽并加快爬网速度。
class scrapy.extensions.httpcache.RFC2616Policy

HTTP缓存存储后端:

  1. Filesystem storage backend(文件存储后端-默认)
    文件系统存储后端可用于HTTP缓存中间件。
class scrapy.extensions.httpcache.FilesystemCacheStorage

settings中配置参数

HTTPCACHE_STORAGE = 'scrapy.extensions.httpcache.FilesystemCacheStorage'
  1. DBM storage backend(DBM存储后端)
    DBM存储后端也可用于HTTP缓存中间件,使用HTTPCACHE_DBM_MODULE设置进行更改 。
    settings中配置参数
HTTPCACHE_STORAGE = 'sscrapy.extensions.httpcache.DbmCacheStorage'
  1. 自定义存储后端
    创建定义Python类来实现缓存存储后端。
class scrapy.extensions.httpcache.CacheStorage

HttpCompressionMiddleware(压缩中间件)

允许从网站发送/接收压缩(gzip,deflate)流量。如果分别安装了brotlipy或zstandard,则此中间件还支持对brotli压缩的响应和 zstd压缩的响应进行解码。

class scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware

settings中配置参数

COMPRESSION_ENABLED = True # 是否启用压缩中间件。

HttpProxyMiddleware(代理中间件)

通过设置对象的proxy元值来设置HTTP代理以用于请求 Request。

class scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware

与Python标准库模块一样urllib.request

http_proxy = 'http://xxxx:xxxx'
https_proxy  = 'http://xxxx:xxxx'
no_proxy

RedirectMiddleware(重新定向中间件)

根据响应状态处理请求的重定向。

class scrapy.downloadermiddlewares.redirect.RedirectMiddleware

settings中配置参数

REDIRECT_ENABLED = True # 是否启用重定向中间件。
REDIRECT_MAX_TIMES = 20 # 单个请求将遵循的最大重定向数。
HTTPERROR_ALLOWED_CODES = [302] # 添加过滤重新定向的响应码

MetaRefreshMiddleware(Meta刷新中间件)

基于meta-refresh html标签处理请求的重定向。

class scrapy.downloadermiddlewares.redirect.MetaRefreshMiddleware

settings中配置参数

METAREFRESH_ENABLED = True # 是否启用Meta Refresh中间件。
METAREFRESH_IGNORE_TAGS = [] # 元标记忽略列表。
METAREFRESH_MAXDELAY = 100 # 重定向后的最大元刷新延迟(以秒为单位)。

RetryMiddleware(重试中间件)

spider完成对所有常规(非失败)页面的爬网之后,将在抓取过程中收集失败的页面并在最后重新安排时间表。

class scrapy.downloadermiddlewares.retry.RetryMiddleware

settings中配置参数

RETRY_ENABLED = True # 是否启用“重试”中间件。
RETRY_TIMES = 2 # 除首次下载外,最大重试次数。
RETRY_HTTP_CODES = [500, 502, 503, 504, 522, 524, 408, 429] # 重试HTTP响应代码列表。

RobotsTxtMiddleware(RobotsTxt 中间件)

过滤出robots.txt排除标准禁止的请求。

classscrapy.downloadermiddlewares.robotstxt.RobotsTxtMiddleware

这部分要是完全遵守协议就别爬了,累啊。

DownloaderStats(下载统计)

用于存储通过它的所有请求,响应和异常的统计信息。

class scrapy.downloadermiddlewares.stats.DownloaderStats

settings中配置参数

DOWNLOADER_STATS = True # 是否启用下载器统计信息收集。

UserAgentMiddleware(用户headers中间件)

spider覆盖默认用户headers、代理的中间件。

class scrapy.downloadermiddlewares.useragent.UserAgentMiddleware

AjaxCrawlMiddleware(AjaxCrawl中间件)

基于元片段html标签找到“ AJAX可抓取”页面的中间件。

class scrapy.downloadermiddlewares.ajaxcrawl.AjaxCrawlMiddleware

settings中配置参数

AJAXCRAWL_ENABLED = True # 是否启用AjaxCrawlMiddleware。
HTTPPROXY_ENABLED = True # 是否启用HttpProxyMiddleware。
HTTPPROXY_AUTH_ENCODING = "latin-1" # 上代理身份验证的默认编码HttpProxyMiddleware。

猜你喜欢

转载自blog.csdn.net/qq_20288327/article/details/113524585