组件

Scrapy 组件是指任何使用 build_from_crawler() 构建其对象的类。

这包括您可以指定给以下设置的类:

第三方 Scrapy 组件也可能允许您定义额外的 Scrapy 组件,通常可以通过设置进行配置,以修改其行为。

从 crawler 初始化

任何 Scrapy 组件都可以选择性地定义以下类方法:

classmethod from_crawler(cls, crawler: scrapy.crawler.Crawler, *args, **kwargs)

根据 crawler 返回一个组件实例。

argskwargs 是某些组件接收的组件特定参数。但是,大多数组件不接收任何参数,而是使用设置

如果一个组件类定义了这个方法,则会调用这个类方法来创建组件的任何实例。

crawler 对象提供了访问所有 Scrapy 核心组件的途径,例如设置信号,允许组件访问它们并将其功能集成到 Scrapy 中。

设置

组件可以通过设置进行配置。

组件可以从其可以通过初始化获取Crawler 对象的 settings 属性中读取任何设置。这包括内置设置和自定义设置。

例如:

class MyExtension:
    @classmethod
    def from_crawler(cls, crawler):
        settings = crawler.settings
        return cls(settings.getbool("LOG_ENABLED"))

    def __init__(self, log_is_enabled=False):
        if log_is_enabled:
            print("log is enabled!")

组件无需以编程方式声明其自定义设置。但是,它们应该记录这些设置,以便用户知道它们的存在以及如何使用。

一个好的实践是使用组件的名称作为自定义设置的前缀,以避免与其他现有(或未来)组件的自定义设置发生冲突。例如,一个名为 WarcCaching 的扩展可以将其自定义设置以 WARC_CACHING_ 为前缀。

另一个好的实践,主要针对用于组件优先级字典的组件,是提供一个名为 <PREFIX>_ENABLED 的布尔设置(例如 WARC_CACHING_ENABLED),以允许在不改变组件优先级字典设置的情况下开启和关闭该组件。您通常可以在初始化期间检查此设置的值,如果为 False,则抛出 NotConfigured

在选择自定义设置名称时,最好查看内置设置的名称,以尝试与它们保持一致性。

强制要求

有时,您的组件可能只适用于某些条件。例如,它们可能需要最低版本的 Scrapy 才能按预期工作,或者它们可能需要某些设置具有特定值。

除了在组件文档中描述这些条件之外,一个好的实践是在运行时如果这些条件不满足,则从组件的 __init__ 方法中抛出异常。

对于下载器中间件扩展项目管道爬虫中间件,您应该抛出 NotConfigured,并将问题的描述作为参数传递给异常,以便将其打印到日志中供用户查看。对于其他组件,您可以自由抛出您认为合适的其他异常;例如,RuntimeError 对于 Scrapy 版本不匹配可能是合理的,而如果问题是设置的值,则 ValueError 可能更好。

如果您的要求是最低 Scrapy 版本,您可以使用 scrapy.__version__ 来强制您的要求。例如:

from packaging.version import parse as parse_version

import scrapy


class MyComponent:
    def __init__(self):
        if parse_version(scrapy.__version__) < parse_version("2.7"):
            raise RuntimeError(
                f"{MyComponent.__qualname__} requires Scrapy 2.7 or "
                f"later, which allow defining the process_spider_output "
                f"method of spider middlewares as an asynchronous "
                f"generator."
            )

API 参考

可以使用以下函数创建组件类的实例:

scrapy.utils.misc.build_from_crawler(objcls: type[T], crawler: Crawler, /, *args: Any, **kwargs: Any) T[源码]

使用其 from_crawlerfrom_settings 构造函数构建类实例。

版本 2.12 新增。

*args**kwargs 会转发给构造函数。

如果结果实例为 None,则抛出 TypeError

在实现组件时,以下函数也可能很有用,用于报告组件类的导入路径,例如在报告问题时:

scrapy.utils.python.global_object_name(obj: Any) str[源码]

返回给定对象的完整导入路径。

>>> from scrapy import Request
>>> global_object_name(Request)
'scrapy.http.request.Request'
>>> global_object_name(Request.replace)
'scrapy.http.request.Request.replace'