扩展

扩展框架提供了一种机制,用于将您自己的自定义功能插入到 Scrapy 中。

扩展只是普通的类。

扩展设置

扩展使用Scrapy 设置来管理其设置,就像任何其他 Scrapy 代码一样。

通常,扩展会以其自己的名称作为其设置的前缀,以避免与现有(和将来)扩展发生冲突。例如,一个假设的处理Google 站点地图的扩展将使用诸如GOOGLESITEMAP_ENABLEDGOOGLESITEMAP_DEPTH等设置。

加载和激活扩展

扩展在启动时加载并激活,方法是为每个正在运行的爬虫实例化扩展类的单个实例。所有扩展初始化代码必须在类__init__方法中执行。

要使扩展可用,请将其添加到EXTENSIONS设置中,该设置位于您的 Scrapy 设置中。在EXTENSIONS中,每个扩展都由一个字符串表示:扩展类名的完整 Python 路径。例如

EXTENSIONS = {
    "scrapy.extensions.corestats.CoreStats": 500,
    "scrapy.extensions.telnet.TelnetConsole": 500,
}

如您所见,EXTENSIONS设置是一个字典,其中键是扩展路径,其值是顺序,定义扩展的加载顺序。 EXTENSIONS设置与 Scrapy 中定义的EXTENSIONS_BASE设置(不应覆盖)合并,然后按顺序排序以获取最终排序的已启用扩展列表。

由于扩展通常彼此不依赖,因此在大多数情况下,它们的加载顺序无关紧要。这就是为什么EXTENSIONS_BASE设置定义所有扩展具有相同的顺序(0)。但是,如果您需要添加一个依赖于其他已加载扩展的扩展,则可以利用此功能。

可用、已启用和已禁用的扩展

并非所有可用的扩展都将启用。其中一些通常依赖于特定的设置。例如,HTTP 缓存扩展默认情况下可用,但除非设置了HTTPCACHE_ENABLED设置,否则将被禁用。

禁用扩展

为了禁用默认情况下启用的扩展(即包含在EXTENSIONS_BASE设置中的扩展),您必须将其顺序设置为None。例如

EXTENSIONS = {
    "scrapy.extensions.corestats.CoreStats": None,
}

编写自己的扩展

每个扩展都是一个 Python 类。Scrapy 扩展(这也包括中间件和管道)的主要入口点是from_crawler类方法,该方法接收一个Crawler实例。通过 Crawler 对象,您可以访问设置、信号、统计信息,还可以控制爬取行为。

通常,扩展连接到信号并执行由它们触发的任务。

最后,如果from_crawler方法引发NotConfigured异常,则扩展将被禁用。否则,扩展将被启用。

扩展示例

在这里,我们将实现一个简单的扩展来说明上一节中描述的概念。此扩展将在每次

  • 爬虫打开时

  • 爬虫关闭时

  • 抓取特定数量的 Item 时

记录一条消息。

扩展将通过MYEXT_ENABLED设置启用,Item 的数量将通过MYEXT_ITEMCOUNT设置指定。

import logging
from scrapy import signals
from scrapy.exceptions import NotConfigured

logger = logging.getLogger(__name__)


class SpiderOpenCloseLogging:
    def __init__(self, item_count):
        self.item_count = item_count
        self.items_scraped = 0

    @classmethod
    def from_crawler(cls, crawler):
        # first check if the extension should be enabled and raise
        # NotConfigured otherwise
        if not crawler.settings.getbool("MYEXT_ENABLED"):
            raise NotConfigured

        # get the number of items from settings
        item_count = crawler.settings.getint("MYEXT_ITEMCOUNT", 1000)

        # instantiate the extension object
        ext = cls(item_count)

        # connect the extension object to signals
        crawler.signals.connect(ext.spider_opened, signal=signals.spider_opened)
        crawler.signals.connect(ext.spider_closed, signal=signals.spider_closed)
        crawler.signals.connect(ext.item_scraped, signal=signals.item_scraped)

        # return the extension object
        return ext

    def spider_opened(self, spider):
        logger.info("opened spider %s", spider.name)

    def spider_closed(self, spider):
        logger.info("closed spider %s", spider.name)

    def item_scraped(self, item, spider):
        self.items_scraped += 1
        if self.items_scraped % self.item_count == 0:
            logger.info("scraped %d items", self.items_scraped)

以下是此扩展的代码

内置扩展参考

通用扩展

class scrapy.extensions.logstats.LogStats[source]

记录基本统计信息,例如已爬取的页面和已抓取的 Item。

核心统计扩展

class scrapy.extensions.corestats.CoreStats[source]

启用核心统计信息的收集,前提是启用了统计信息收集(请参阅统计信息收集)。

Telnet 控制台扩展

class scrapy.extensions.telnet.TelnetConsole[source]

提供一个 Telnet 控制台,用于进入当前正在运行的 Scrapy 进程中的 Python 解释器,这对于调试非常有用。

Telnet 控制台必须通过TELNETCONSOLE_ENABLED设置启用,服务器将在TELNETCONSOLE_PORT中指定的端口监听。

内存使用扩展

class scrapy.extensions.memusage.MemoryUsage[source]

注意

此扩展在 Windows 中不起作用。

监视运行爬虫的 Scrapy 进程使用的内存,以及

  1. 当内存超过某个值时发送通知邮件

  2. 当内存超过某个值时关闭爬虫

当达到某个警告值时(MEMUSAGE_WARNING_MB)和达到最大值时(MEMUSAGE_LIMIT_MB),可以触发通知邮件,这也会导致爬虫关闭并终止 Scrapy 进程。

此扩展通过MEMUSAGE_ENABLED设置启用,并可以通过以下设置进行配置

内存调试器扩展

class scrapy.extensions.memdebug.MemoryDebugger[source]

用于调试内存使用的扩展。它收集有关

要启用此扩展,请打开 MEMDEBUG_ENABLED 设置。信息将存储在统计数据中。

Spider 状态扩展

class scrapy.extensions.spiderstate.SpiderState[source]

通过在爬取之前加载并保存蜘蛛状态数据来管理它。

JOBDIR 设置赋予一个值以启用此扩展。启用后,此扩展将管理 state 属性您的 Spider 实例。

  • 当您的蜘蛛关闭时 (spider_closed),其 state 属性的内容将序列化到 JOBDIR 文件夹中名为 spider.state 的文件中。

  • 当您的蜘蛛打开时 (spider_opened),如果之前生成的 spider.state 文件存在于 JOBDIR 文件夹中,它将被加载到 state 属性中。

有关示例,请参阅 在批次之间保持持久状态

关闭蜘蛛扩展

class scrapy.extensions.closespider.CloseSpider[source]

当满足某些条件时,自动关闭蜘蛛,并为每个条件使用特定的关闭原因。

关闭蜘蛛的条件可以通过以下设置进行配置

注意

当满足某个关闭条件时,当前位于下载器队列中的请求(最多 CONCURRENT_REQUESTS 个请求)仍将被处理。

CLOSESPIDER_TIMEOUT

默认值:0

一个整数,指定秒数。如果蜘蛛保持打开状态超过该秒数,它将自动关闭,原因是 closespider_timeout。如果为零(或未设置),则蜘蛛不会因超时而关闭。

CLOSESPIDER_TIMEOUT_NO_ITEM

默认值:0

一个整数,指定秒数。如果蜘蛛在过去这么多秒内没有生成任何项目,它将关闭,原因是 closespider_timeout_no_item。如果为零(或未设置),则蜘蛛无论是否生成任何项目都不会关闭。

CLOSESPIDER_ITEMCOUNT

默认值:0

一个整数,指定项目的数量。如果蜘蛛抓取的项目数量超过该数量,并且这些项目通过了项目管道,则蜘蛛将关闭,原因是 closespider_itemcount。如果为零(或未设置),则蜘蛛不会因通过的项目数量而关闭。

CLOSESPIDER_PAGECOUNT

默认值:0

一个整数,指定要爬取的响应的最大数量。如果蜘蛛爬取的数量超过该数量,则蜘蛛将关闭,原因是 closespider_pagecount。如果为零(或未设置),则蜘蛛不会因爬取的响应数量而关闭。

CLOSESPIDER_PAGECOUNT_NO_ITEM

默认值:0

一个整数,指定连续爬取而没有抓取到项目的响应的最大数量。如果蜘蛛连续爬取的响应数量超过该数量,并且在此期间没有抓取到任何项目,则蜘蛛将关闭,原因是 closespider_pagecount_no_item。如果为零(或未设置),则蜘蛛不会因没有项目的爬取响应数量而关闭。

CLOSESPIDER_ERRORCOUNT

默认值:0

一个整数,指定在关闭蜘蛛之前要接收的错误的最大数量。如果蜘蛛生成的错误数量超过该数量,它将关闭,原因是 closespider_errorcount。如果为零(或未设置),则蜘蛛不会因错误数量而关闭。

统计邮件发送器扩展

class scrapy.extensions.statsmailer.StatsMailer[source]

此简单的扩展可用于在每次某个域完成抓取后发送通知电子邮件,包括收集到的 Scrapy 统计信息。电子邮件将发送到 STATSMAILER_RCPTS 设置中指定的所有收件人。

可以使用 MailSender 类发送电子邮件。要查看参数的完整列表,包括有关如何实例化 MailSender 和使用邮件设置的示例,请参阅 发送电子邮件

定期日志扩展

class scrapy.extensions.periodic_log.PeriodicLog[source]

此扩展定期将丰富的统计数据作为 JSON 对象记录。

2023-08-04 02:30:57 [scrapy.extensions.logstats] INFO: Crawled 976 pages (at 162 pages/min), scraped 925 items (at 161 items/min)
2023-08-04 02:30:57 [scrapy.extensions.periodic_log] INFO: {
    "delta": {
        "downloader/request_bytes": 55582,
        "downloader/request_count": 162,
        "downloader/request_method_count/GET": 162,
        "downloader/response_bytes": 618133,
        "downloader/response_count": 162,
        "downloader/response_status_count/200": 162,
        "item_scraped_count": 161
    },
    "stats": {
        "downloader/request_bytes": 338243,
        "downloader/request_count": 992,
        "downloader/request_method_count/GET": 992,
        "downloader/response_bytes": 3836736,
        "downloader/response_count": 976,
        "downloader/response_status_count/200": 976,
        "item_scraped_count": 925,
        "log_count/INFO": 21,
        "log_count/WARNING": 1,
        "scheduler/dequeued": 992,
        "scheduler/dequeued/memory": 992,
        "scheduler/enqueued": 1050,
        "scheduler/enqueued/memory": 1050
    },
    "time": {
        "elapsed": 360.008903,
        "log_interval": 60.0,
        "log_interval_real": 60.006694,
        "start_time": "2023-08-03 23:24:57",
        "utcnow": "2023-08-03 23:30:57"
    }
}

此扩展记录以下可配置的部分

  • "delta" 显示自上次统计数据日志消息以来某些数值统计数据发生了怎样的变化。

    PERIODIC_LOG_DELTA 设置确定目标统计数据。它们必须具有 intfloat 值。

  • "stats" 显示某些统计数据的当前值。

    PERIODIC_LOG_STATS 设置确定目标统计数据。

  • "time" 显示详细的计时数据。

    PERIODIC_LOG_TIMING_ENABLED 设置确定是否显示此部分。

此扩展在开始时记录数据,然后以固定的时间间隔(可通过 LOGSTATS_INTERVAL 设置配置)记录数据,最后在爬取结束前记录数据。

扩展配置示例

custom_settings = {
    "LOG_LEVEL": "INFO",
    "PERIODIC_LOG_STATS": {
        "include": ["downloader/", "scheduler/", "log_count/", "item_scraped_count/"],
    },
    "PERIODIC_LOG_DELTA": {"include": ["downloader/"]},
    "PERIODIC_LOG_TIMING_ENABLED": True,
    "EXTENSIONS": {
        "scrapy.extensions.periodic_log.PeriodicLog": 0,
    },
}
PERIODIC_LOG_DELTA

默认值:None

  • "PERIODIC_LOG_DELTA": True - 显示所有 intfloat 统计数据的值的变化。

  • "PERIODIC_LOG_DELTA": {"include": ["downloader/", "scheduler/"]} - 显示名称包含任何配置的子字符串的统计数据的值的变化。

  • "PERIODIC_LOG_DELTA": {"exclude": ["downloader/"]} - 显示名称不包含任何配置的子字符串的所有统计数据的值的变化。

PERIODIC_LOG_STATS

默认值:None

  • "PERIODIC_LOG_STATS": True - 显示所有统计数据的当前值。

  • "PERIODIC_LOG_STATS": {"include": ["downloader/", "scheduler/"]} - 显示名称包含任何配置的子字符串的统计数据的当前值。

  • "PERIODIC_LOG_STATS": {"exclude": ["downloader/"]} - 显示名称不包含任何配置的子字符串的所有统计数据的当前值。

PERIODIC_LOG_TIMING_ENABLED

默认值:False

True 启用计时数据的记录(即 "time" 部分)。

调试扩展

堆栈跟踪转储扩展

class scrapy.extensions.periodic_log.StackTraceDump

当收到SIGQUITSIGUSR2信号时,转储正在运行的进程的信息。转储的信息如下

  1. 引擎状态(使用scrapy.utils.engine.get_engine_status()

  2. 活动引用(参见使用trackref调试内存泄漏

  3. 所有线程的堆栈跟踪

转储堆栈跟踪和引擎状态后,Scrapy进程将继续正常运行。

此扩展仅在符合POSIX的平台(即不包括Windows)上有效,因为SIGQUITSIGUSR2信号在Windows上不可用。

至少有两种方法可以向Scrapy发送SIGQUIT信号

  1. 在Scrapy进程运行时按Ctrl-\(仅限Linux?)

  2. 运行以下命令(假设<pid>是Scrapy进程的进程ID)

    kill -QUIT <pid>
    

调试器扩展

class scrapy.extensions.periodic_log.Debugger

当收到SIGUSR2信号时,在正在运行的Scrapy进程中调用Python调试器。退出调试器后,Scrapy进程将继续正常运行。

此扩展仅在符合POSIX的平台(即不包括Windows)上有效。