Scrapy中间件订单

use*_*ser 6 python middleware scrapy

Scrapy 文档说:

第一个中间件是靠近引擎的中间件,最后一个是靠近下载器的中间件.

要确定分配给中间件的顺序,请参阅DOWNLOADER_MIDDLEWARES_BASE设置,并根据要插入中间件的位置选择一个值.订单确实很重要,因为每个中间件执行不同的操作,您的中间件可能依赖于应用的某些先前(或后续)中间件

我并不完全清楚,更高的值是否会导致中间件首先被执行,反之亦然.

例如

'myproject.middlewares.MW1': 543,
'myproject.middlewares.MW2': 542,
Run Code Online (Sandbox Code Playgroud)

题 :

  1. 哪些将首先执行?我的试验说MW2将是第一个.
  2. 什么是订单的有效范围?0 - 999?

und*_*run 8

我知道这已经得到了解答,但实际上这是一个更复杂的事情 - 请求和响应按相反的顺序处理.

你可以这样想:

  • 0 - 引擎发出请求
  • 1..inf - process_request中间件调用
  • inf - 实际下载发生(如果请求中间件没有处理它)
  • inf..1 - process_resonse中间件调用
  • 0 - 引擎收到的响应

所以...如果我将我的中间件标记为数字1,那么将执行FIRST请求中间件并执行LAST响应中间件...如果我的中间件为901,则执行最终请求中间件并执行FIRST响应中间件(如果只定义了默认的中间件).

真的答案是它令人困惑.请求的开始距离引擎最近(为零),请求的结尾最接近下载程序(高位数).响应的开始最接近下载器(高数字),​​响应的结尾最接近引擎(零).它就像是从引擎中跳出来的......这里是来自scrapy的相关代码,它使得这一切变得如此有趣(使用从MiddlewareManager复制的init作为参考,仅包括相关方法):

class DownloaderMiddlewareManager(MiddlewareManager):
    def __init__(self, *middlewares):
        self.middlewares = middlewares
        self.methods = defaultdict(list)
        for mw in middlewares:
            self._add_middleware(mw)

    def _add_middleware(self, mw):
        if hasattr(mw, 'process_request'):
            self.methods['process_request'].append(mw.process_request)
        if hasattr(mw, 'process_response'):
            self.methods['process_response'].insert(0, mw.process_response)
        if hasattr(mw, 'process_exception'):
            self.methods['process_exception'].insert(0, mw.process_exception)
Run Code Online (Sandbox Code Playgroud)

如您所见,请求方法按排序顺序(后面添加了更高的数字),并在开头插入响应和异常方法(更高的数字是第一个).


war*_*iuc 3

  1. 其中哪一个将首先被执行?我的试验表明《MW2》将是第一个。

正如您引用的文档:

第一个中间件是更接近引擎的中间件,最后一个中间件是更接近下载器的中间件。

因此,值为 542 的下载器中间件会在值为 543 的中间件之前执行。这意味着首先myproject.middlewares.MW1.process_request(request, spider)调用,在更改(如果需要)请求后,将其传递给下一个下载器中间件。

  1. 订单的有效范围是多少?0 - 999?

该值为整数。

更新:

看看架构

另外,完整的报价

DOWNLOADER_MIDDLEWARES 设置与 Scrapy 中定义的 DOWNLOADER_MIDDLEWARES_BASE 设置合并(并不意味着被覆盖),然后按顺序排序以获得启用的中间件的最终排序列表:第一个中间件是距离引擎较近的中间件,最后一个中间件是距离下载器更近的一个。

因此,由于值是整数,因此它们具有 Python 整数范围。