信号

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

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

您可以通过信号 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

延迟信号处理器

某些信号支持从其处理程序返回Deferred可等待对象,允许您运行不会阻塞 Scrapy 的异步代码。如果信号处理程序返回这些对象之一,Scrapy 会等待该异步操作完成。

让我们使用协程举个例子

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 内置信号及其含义的列表。

引擎信号

engine_started

scrapy.signals.engine_started()

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

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

注意

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

engine_stopped

scrapy.signals.engine_stopped()

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

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

数据项信号

注意

由于最多有CONCURRENT_ITEMS 个数据项并行处理,因此许多延迟使用DeferredList 一起触发。因此,下一批等待DeferredList 触发,然后为下一批抓取的数据项运行相应的数据项信号处理程序。

item_scraped

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

当一个数据项被抓取后发送,在它通过所有数据项管道 阶段(未被丢弃)之后。

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

参数:

item_dropped

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

在某个阶段引发DropItem 异常时,数据项从数据项管道 中被丢弃后发送。

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

参数:

item_error

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

数据项管道 生成错误(即引发异常)时发送,除了DropItem 异常。

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

参数:

爬虫信号

spider_closed

scrapy.signals.spider_closed(spider, reason)

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

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

参数:
  • spider (Spider 对象) – 已关闭的蜘蛛

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

spider_opened

scrapy.signals.spider_opened(spider)

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

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

参数:

spider (Spider 对象) – 已打开的蜘蛛

spider_idle

scrapy.signals.spider_idle(spider)

当蜘蛛处于空闲状态时发送,这意味着蜘蛛没有进一步的

  • 等待下载的请求

  • 已安排的请求

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

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

您可以引发DontCloseSpider异常以防止蜘蛛关闭。

或者,您可以引发CloseSpider异常以提供自定义蜘蛛关闭原因。空闲处理程序是放置一些代码以评估最终蜘蛛结果并相应地更新最终关闭原因(例如,将其设置为“too_few_results”而不是“finished”)的理想位置。

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

参数:

spider (Spider 对象) – 处于空闲状态的蜘蛛

注意

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

spider_error

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

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

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

参数:

feed_slot_closed

scrapy.signals.feed_slot_closed(slot)

feed 导出槽关闭时发送。

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

参数:

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

feed_exporter_closed

scrapy.signals.feed_exporter_closed()

feed 导出扩展关闭时发送,在扩展处理spider_closed信号期间,在所有feed导出都已处理之后。

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

请求信号

request_scheduled

scrapy.signals.request_scheduled(request, spider)

当引擎被要求安排一个Request以便稍后下载时发送,在请求到达调度程序之前。

引发IgnoreRequest以在请求到达调度程序之前将其丢弃。

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

版本 2.11.2 中的新功能: 允许使用IgnoreRequest丢弃请求。

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

  • spider (Spider 对象) – 产生请求的蜘蛛

request_dropped

scrapy.signals.request_dropped(request, spider)

当引擎安排稍后下载的Request被调度程序拒绝时发送。

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

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

  • spider (Spider 对象) – 产生请求的蜘蛛

request_reached_downloader

scrapy.signals.request_reached_downloader(request, spider)

Request到达下载器时发送。

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

参数:
  • request (Request 对象) – 已到达下载器的请求

  • spider (Spider 对象) – 产生请求的蜘蛛

request_left_downloader

scrapy.signals.request_left_downloader(request, spider)

版本 2.0 中的新功能。

Request离开下载器时发送,即使发生错误也是如此。

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

参数:
  • request (Request 对象) – 已到达下载器的请求

  • spider (Spider 对象) – 产生请求的蜘蛛

bytes_received

版本 2.2 中的新功能。

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

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

此信号的处理程序可以在响应正在下载过程中停止下载,方法是引发StopDownload异常。有关其他信息和示例,请参阅停止下载响应主题。

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

参数:
  • data (bytes 对象) – 下载处理程序接收到的数据

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

  • spider (Spider 对象) – 与响应关联的蜘蛛

headers_received

2.5 版本新增。

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

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

此信号的处理程序可以在响应正在下载过程中停止下载,方法是引发StopDownload异常。有关其他信息和示例,请参阅停止下载响应主题。

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

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

  • body_length (int) – 响应体预计大小(字节)

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

  • spider (Spider 对象) – 与响应关联的蜘蛛

响应信号

response_received

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

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

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

参数:
  • response (Response 对象) – 收到的响应

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

  • spider (Spider 对象) – 响应的目标蜘蛛

注意

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

response_downloaded

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

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

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

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

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

  • spider (Spider 对象) – 响应的目标蜘蛛