扩展
与其他组件不同,扩展在 Scrapy 中没有特定的角色。它们是“通配符”组件,可用于任何不适合任何其他类型组件角色的功能。
加载和激活扩展
扩展在启动时加载,每个运行的爬虫都会创建一个扩展类的单个实例。
要启用扩展,请将其添加到 EXTENSIONS 设置中。例如:
EXTENSIONS = {
"scrapy.extensions.corestats.CoreStats": 500,
"scrapy.extensions.telnet.TelnetConsole": 500,
}
EXTENSIONS 与 EXTENSIONS_BASE(不应被覆盖)合并,结果值中的优先级决定了加载顺序。
由于扩展通常不相互依赖,它们的加载顺序在大多数情况下无关紧要。这就是为什么 EXTENSIONS_BASE 设置将所有扩展定义为相同的顺序 (0)。但是,如果你添加的扩展依赖于其他扩展已被加载,你可能需要仔细使用优先级。
编写自己的扩展
每个扩展都是一个组件。
通常,扩展连接到信号并执行由信号触发的任务。
示例扩展
在这里,我们将实现一个简单的扩展,以说明前一节中描述的概念。此扩展将在以下情况时记录一条消息:
- 爬虫打开时
- 爬虫关闭时
- 抓取到特定数量的项目时
该扩展将通过 MYEXT_ENABLED 设置启用,项目数量将通过 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):
# 首先检查是否应启用扩展,否则引发 NotConfigured
if not crawler.settings.getbool("MYEXT_ENABLED"):
raise NotConfigured
# 从设置中获取项目数量
item_count = crawler.settings.getint("MYEXT_ITEMCOUNT", 1000)
# 实例化扩展对象
ext = cls(item_count)
# 将扩展对象连接到信号
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 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)
内置扩展参考
通用扩展
Log Stats 扩展
class scrapy.extensions.logstats.LogStats[source]
记录基本统计信息,例如抓取页面和抓取项目。
Core Stats 扩展
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 进程使用的内存,该进程运行爬虫并:
- 当超过某个值时发送通知电子邮件
- 当超过某个值时关闭爬虫
当达到某个警告值(MEMUSAGE_WARNING_MB)和达到最大值(MEMUSAGE_LIMIT_MB)时,可以触发通知电子邮件,后者还会导致爬虫关闭并终止 Scrapy 进程。
此扩展通过 MEMUSAGE_ENABLED 设置启用,可以通过以下设置进行配置:
MEMUSAGE_LIMIT_MBMEMUSAGE_WARNING_MBMEMUSAGE_NOTIFY_MAILMEMUSAGE_CHECK_INTERVAL_SECONDS
内存调试器扩展
class scrapy.extensions.memdebug.MemoryDebugger[source]
用于调试内存使用的扩展。它收集有关以下信息:
- Python 垃圾回收器未收集的对象
- 应该被回收但仍存活的对象。有关更多信息,请参阅使用 trackref 调试内存泄漏
要启用此扩展,请打开 MEMDEBUG_ENABLED 设置。信息将存储在统计信息中。
爬虫状态扩展
class scrapy.extensions.spiderstate.SpiderState[source]
通过在抓取之前加载并在之后保存来管理爬虫状态数据。
为 JOBDIR 设置一个值以启用此扩展。启用后,此扩展管理你的 Spider 实例的 state 属性:
- 当你的爬虫关闭时 (
spider_closed),其state属性的内容将序列化到JOBDIR文件夹中名为spider.state的文件中。 - 当你的爬虫打开时 (
spider_opened),如果JOBDIR文件夹中存在先前生成的spider.state文件,它将被加载到state属性中。
有关示例,请参阅在批次之间保持持久状态。
关闭爬虫扩展
class scrapy.extensions.closespider.CloseSpider[source]
当满足某些条件时自动关闭爬虫,为每个条件使用特定的关闭原因。
关闭爬虫的条件可以通过以下设置进行配置:
CLOSESPIDER_TIMEOUTCLOSESPIDER_TIMEOUT_NO_ITEMCLOSESPIDER_ITEMCOUNTCLOSESPIDER_PAGECOUNTCLOSESPIDER_ERRORCOUNT
注意: 当满足某个关闭条件时,当前在下载器队列中的请求(最多 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设置确定目标统计信息。它们必须是int或float值。
"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- 显示所有int和float统计值的增量。"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
当收到 SIGQUIT 或 SIGUSR2 信号时,转储有关运行进程的信息。转储的信息如下:
- 引擎状态(使用
scrapy.utils.engine.get_engine_status()) - 活跃引用(请参阅使用 trackref 调试内存泄漏)
- 所有线程的堆栈跟踪
转储堆栈跟踪和引擎状态后,Scrapy 进程将继续正常运行。
此扩展仅适用于符合 POSIX 标准的平台(即不包括 Windows),因为 SIGQUIT 和 SIGUSR2 信号在 Windows 上不可用。
至少有两种方法可以向 Scrapy 发送 SIGQUIT 信号:
- 在 Scrapy 进程运行时按下
Ctrl-\(仅限 Linux?) - 运行此命令(假设
<pid>是 Scrapy 进程的进程 ID):kill -QUIT <pid>
调试器扩展
class scrapy.extensions.periodic_log.Debugger
当收到 SIGUSR2 信号时,在运行中的 Scrapy 进程中调用 Python 调试器。退出调试器后,Scrapy 进程将继续正常运行。
此扩展仅适用于符合 POSIX 标准的平台(即不包括 Windows)。