信号

Scrapy 广泛使用信号来通知某些事件的发生。你可以在你的 Scrapy 项目中捕获一些这些信号(例如,使用 扩展)以执行额外的任务或扩展 Scrapy 以添加未提供的功能。

尽管信号提供了多个参数,但捕获它们的处理程序不需要接受所有参数 - 信号分发机制只会传递处理程序接收到的参数。

您可以通过Signals API连接到信号(或发送您自己的信号)。

这里是一个简单的示例,展示如何捕获信号并执行一些操作:

from scrapy import signals
from scrapy import Spider


class DmozSpider(Spider):
    name = "dmoz"
    allowed_domains = ["dmoz.org"]
    start_urls = [
        "http://www.dmoz.org/Computers/Programming/Languages/Python/Books/",
        "http://www.dmoz.org/Computers/Programming/Languages/Python/Resources/",
    ]

    @classmethod
    def from_crawler(cls, crawler, *args, **kwargs):
        spider = super(DmozSpider, cls).from_crawler(crawler, *args, **kwargs)
        crawler.signals.connect(spider.spider_closed, signal=signals.spider_closed)
        return spider

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

    def parse(self, response):
        pass

延迟信号处理程序

一些信号支持从它们的处理程序中返回Deferredawaitable objects,允许你运行不阻塞Scrapy的异步代码。如果信号处理程序返回这些对象之一,Scrapy会等待该异步操作完成。

让我们以使用coroutines为例:

import scrapy


class SignalSpider(scrapy.Spider):
    name = "signals"
    start_urls = ["https://quotes.toscrape.com/page/1/"]

    @classmethod
    def from_crawler(cls, crawler, *args, **kwargs):
        spider = super(SignalSpider, cls).from_crawler(crawler, *args, **kwargs)
        crawler.signals.connect(spider.item_scraped, signal=signals.item_scraped)
        return spider

    async def item_scraped(self, item):
        # Send the scraped item to the server
        response = await treq.post(
            "http://example.com/post",
            json.dumps(item).encode("ascii"),
            headers={b"Content-Type": [b"application/json"]},
        )

        return response

    def parse(self, response):
        for quote in response.css("div.quote"):
            yield {
                "text": quote.css("span.text::text").get(),
                "author": quote.css("small.author::text").get(),
                "tags": quote.css("div.tags a.tag::text").getall(),
            }

请参阅下面的内置信号参考,以了解哪些信号支持 Deferred可等待对象

内置信号参考

以下是Scrapy内置信号及其含义的列表。

引擎信号

引擎已启动

scrapy.signals.engine_started()

当Scrapy引擎开始爬取时发送。

此信号支持从其处理程序返回延迟对象。

注意

此信号可能在spider_opened信号之后触发, 具体取决于蜘蛛的启动方式。因此不要依赖此信号 在spider_opened之前触发。

引擎已停止

scrapy.signals.engine_stopped()

当Scrapy引擎停止时发送(例如,当爬取过程完成时)。

此信号支持从其处理程序返回延迟对象。

项目信号

注意

在最大CONCURRENT_ITEMS项目并行处理时,许多延迟项会一起触发使用DeferredList。因此,下一批等待DeferredList触发,然后为下一批抓取的项目运行相应的项目信号处理程序。

已抓取的项目

scrapy.signals.item_scraped(item, response, spider)

当一个项目被爬取后,在它通过了所有的Item Pipeline阶段(未被丢弃)后发送。

此信号支持从其处理程序返回延迟对象。

Parameters:
  • item (item object) – 抓取的项目

  • spider (Spider 对象) – 抓取该项目的爬虫

  • response (Response | None) – 抓取项目的响应,或者如果是从start_requests()生成的,则为None

item_dropped

scrapy.signals.item_dropped(item, response, exception, spider)

当某个阶段引发DropItem异常时,在从Item Pipeline中删除项目后发送。

此信号支持从其处理程序返回延迟对象。

Parameters:

项目错误

scrapy.signals.item_error(item, response, spider, failure)

Item Pipeline生成错误时(即引发异常)发送,除了DropItem异常。

此信号支持从其处理程序返回延迟对象。

Parameters:

爬虫信号

spider_closed

scrapy.signals.spider_closed(spider, reason)

在蜘蛛关闭后发送。这可以用于释放每个蜘蛛在spider_opened上保留的资源。

此信号支持从其处理程序返回延迟对象。

Parameters:
  • spider (Spider 对象) – 已关闭的爬虫

  • 原因 (str) – 一个描述蜘蛛关闭原因的字符串。如果蜘蛛因为完成抓取而关闭,原因是 'finished'。否则,如果蜘蛛是通过调用 close_spider 引擎方法手动关闭的,那么原因是该方法 reason 参数中传递的原因(默认为 'cancelled')。如果引擎被关闭(例如,通过按下 Ctrl-C 停止它),原因将是 'shutdown'

spider_opened

scrapy.signals.spider_opened(spider)

在蜘蛛被打开进行爬取后发送。这通常用于保留每个蜘蛛的资源,但也可以用于在蜘蛛打开时需要执行的任何任务。

此信号支持从其处理程序返回延迟对象。

Parameters:

spider (Spider 对象) – 已打开的爬虫

spider_idle

scrapy.signals.spider_idle(spider)

当爬虫进入空闲状态时发送,这意味着爬虫没有进一步的操作:

  • 等待下载的请求

  • 已安排的请求

  • 在项目管道中正在处理的项

如果在此信号的所有处理程序完成后,空闲状态仍然持续,引擎将开始关闭蜘蛛。在蜘蛛完成关闭后,将发送spider_closed信号。

你可以抛出一个 DontCloseSpider 异常来防止爬虫被关闭。

或者,你可以抛出一个 CloseSpider 异常来提供一个自定义的爬虫关闭原因。空闲处理器是放置一些代码的理想位置,这些代码可以评估最终的爬虫结果并相应地更新最终的关闭原因(例如,将其设置为‘too_few_results’而不是‘finished’)。

此信号不支持从其处理程序返回延迟。

Parameters:

spider (Spider 对象) – 已经空闲的爬虫

注意

在你的spider_idle处理程序中调度一些请求并不保证它可以防止蜘蛛被关闭,尽管有时可以。这是因为如果所有调度的请求都被调度器拒绝(例如由于重复而被过滤),蜘蛛可能仍然保持空闲状态。

spider_error

scrapy.signals.spider_error(failure, response, spider)

当蜘蛛回调生成错误时发送(即引发异常)。

此信号不支持从其处理程序返回延迟。

Parameters:

feed_slot_closed

scrapy.signals.feed_slot_closed(slot)

feed exports槽关闭时发送。

此信号支持从其处理程序返回延迟对象。

Parameters:

slot (scrapy.extensions.feedexport.FeedSlot) – 槽已关闭

feed_exporter_closed

scrapy.signals.feed_exporter_closed()

feed exports扩展关闭时发送, 在扩展处理spider_closed信号期间, 在所有feed导出处理完毕后。

此信号支持从其处理程序返回延迟对象。

请求信号

请求已安排

scrapy.signals.request_scheduled(request, spider)

当引擎被要求安排一个Request时发送,该请求将在稍后下载,在请求到达scheduler之前。

在请求到达调度器之前,抛出 IgnoreRequest 以丢弃该请求。

此信号不支持从其处理程序返回延迟。

新版本2.11.2新增:允许使用IgnoreRequest丢弃请求。

Parameters:
  • request (Request 对象) – 到达调度程序的请求

  • spider (Spider 对象) – 生成请求的爬虫

请求被丢弃

scrapy.signals.request_dropped(request, spider)

当引擎计划稍后下载的Request被调度器拒绝时发送。

此信号不支持从其处理程序返回延迟。

Parameters:
  • request (Request 对象) – 到达调度程序的请求

  • spider (Spider 对象) – 生成请求的爬虫

请求到达下载器

scrapy.signals.request_reached_downloader(request, spider)

Request到达下载器时发送。

此信号不支持从其处理程序返回延迟。

Parameters:
  • 请求 (Request 对象) – 到达下载器的请求

  • spider (Spider 对象) – 生成请求的爬虫

request_left_downloader

scrapy.signals.request_left_downloader(request, spider)

版本2.0新增。

Request离开下载器时发送,即使在失败的情况下。

此信号不支持从其处理程序返回延迟。

Parameters:
  • 请求 (Request 对象) – 到达下载器的请求

  • spider (Spider 对象) – 生成请求的爬虫

接收的字节数

新版本2.2新增。

scrapy.signals.bytes_received(data, request, spider)

当为特定请求接收到一组字节时,由HTTP 1.1和S3下载处理程序发送。对于同一请求,此信号可能会多次触发,每次都有部分数据。例如,对于25 kb的响应,可能的情况是触发两次信号,每次有10 kb的数据,最后一次有5 kb的数据。

此信号的处理程序可以通过引发StopDownload异常来停止正在进行的响应下载。请参阅停止响应下载主题以获取更多信息和示例。

此信号不支持从其处理程序返回延迟。

Parameters:
  • data (bytes 对象) – 下载处理器接收到的数据

  • 请求 (Request 对象) – 生成下载的请求

  • spider (Spider 对象) – 与响应关联的爬虫

headers_received

新版本2.5中新增。

scrapy.signals.headers_received(headers, body_length, request, spider)

当给定请求的响应头可用时,在下载任何额外内容之前,由HTTP 1.1和S3下载处理程序发送。

此信号的处理程序可以通过引发StopDownload异常来停止正在进行的响应下载。请参阅停止响应下载主题以获取更多信息和示例。

此信号不支持从其处理程序返回延迟。

Parameters:
  • headers (scrapy.http.headers.Headers 对象) – 下载处理器接收到的头部信息

  • body_length (int) – 响应体的预期大小,以字节为单位

  • 请求 (Request 对象) – 生成下载的请求

  • spider (Spider 对象) – 与响应关联的爬虫

响应信号

响应接收

scrapy.signals.response_received(response, request, spider)

当引擎从下载器接收到一个新的Response时发送。

此信号不支持从其处理程序返回延迟。

Parameters:
  • response (Response 对象) – 接收到的响应

  • 请求 (Request 对象) – 生成响应的请求

  • spider (Spider 对象) – 响应所针对的蜘蛛

注意

request 参数可能不包含到达下载器的原始请求,如果 下载器中间件 修改了 Response 对象并设置了特定的 request 属性。

response_downloaded

scrapy.signals.response_downloaded(response, request, spider)

由下载器在下载完HTTPResponse后立即发送。

此信号不支持从其处理程序返回延迟。

Parameters:
  • response (Response 对象) – 下载的响应

  • 请求 (Request 对象) – 生成响应的请求

  • spider (Spider 对象) – 响应所针对的蜘蛛