信号(Signals)
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
或 awaitable 对象,允许您运行不阻塞 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
和 awaitable 对象。
内置信号参考
以下是 Scrapy 内置信号及其含义的列表。
引擎信号
engine_started
- scrapy.signals.engine_started()
在 Scrapy 引擎开始爬取时发送。
此信号支持其处理器返回 deferreds。
注意
此信号可能在 spider_opened
信号之后触发,具体取决于爬虫的启动方式。因此,请**不要**依赖此信号在 spider_opened
之前触发。
engine_stopped
- scrapy.signals.engine_stopped()
在 Scrapy 引擎停止时发送(例如,当一个爬取进程完成时)。
此信号支持其处理器返回 deferreds。
scheduler_empty
- scrapy.signals.scheduler_empty()
每当引擎向 调度器 请求待处理的请求(即调用其
next_request()
方法)并且调度器返回 None 时发送。请参阅 延迟启动请求迭代 以查看示例。
数据项信号
注意
由于最多 CONCURRENT_ITEMS
数据项并行处理,许多 deferreds 会使用 DeferredList
一起触发。因此,下一批会等待 DeferredList
触发,然后为下一批抓取的数据项运行相应的 数据项信号处理器。
item_scraped
item_dropped
item_error
爬虫信号
spider_closed
- scrapy.signals.spider_closed(spider, reason)
在爬虫关闭后发送。这可用于释放
spider_opened
上预留的每个爬虫资源。此信号支持其处理器返回 deferreds。
spider_opened
spider_idle
- scrapy.signals.spider_idle(spider)
在爬虫进入空闲状态时发送,这意味着爬虫没有更多
等待下载的请求
已调度的请求
正在数据项管道中处理的数据项
如果在该信号的所有处理器完成后空闲状态仍然持续,引擎将开始关闭爬虫。爬虫关闭完成后,将发送
spider_closed
信号。您可以引发
DontCloseSpider
异常来阻止爬虫被关闭。或者,您可以引发
CloseSpider
异常以提供自定义的爬虫关闭原因。空闲处理器是放置评估最终爬虫结果并相应更新最终关闭原因(例如,将其设置为 ‘too_few_results’ 而不是 ‘finished’)代码的理想位置。此信号不支持其处理器返回 deferreds。
- 参数:
spider (
Spider
对象) – 进入空闲状态的爬虫
注意
在您的 spider_idle
处理器中调度一些请求并不能保证阻止爬虫被关闭,尽管有时可以。这是因为如果所有调度的请求都被调度器拒绝(例如,因重复而被过滤),爬虫可能仍然保持空闲状态。
spider_error
- scrapy.signals.spider_error(failure, response, spider)
当爬虫回调产生错误(即引发异常)时发送。
此信号不支持其处理器返回 deferreds。
- 参数:
failure (twisted.python.failure.Failure) – 引发的异常
response (
Response
对象) – 引发异常时正在处理的响应spider (
Spider
对象) – 引发异常的爬虫
feed_slot_closed
feed_exporter_closed
- scrapy.signals.feed_exporter_closed()
在 Feed 导出 扩展关闭时发送,发生在扩展处理
spider_closed
信号期间,所有 Feed 导出处理完成后。此信号支持其处理器返回 deferreds。
请求信号
request_scheduled
- scrapy.signals.request_scheduled(request, spider)
当引擎被要求调度一个
Request
以供稍后下载,在请求到达 调度器 之前发送。引发
IgnoreRequest
以在请求到达调度器之前丢弃它。此信号不支持其处理器返回 deferreds。
2.11.2 新增:允许使用
IgnoreRequest
丢弃请求。
request_dropped
request_reached_downloader
request_left_downloader
bytes_received
2.2 新增。
- scrapy.signals.bytes_received(data, request, spider)
由 HTTP 1.1 和 S3 下载处理器在接收到特定请求的一组字节时发送。对于同一个请求,此信号可能触发多次,每次带有部分数据。例如,对于一个 25 kb 的响应,可能出现的情况是触发两次信号,每次带有 10 kb 数据,最后一次带有 5 kb 数据。
此信号的处理器可以通过引发
StopDownload
异常来停止正在进行中的响应下载。有关更多信息和示例,请参阅 停止响应下载 主题。此信号不支持其处理器返回 deferreds。
headers_received
2.5 新增。
- scrapy.signals.headers_received(headers, body_length, request, spider)
由 HTTP 1.1 和 S3 下载处理器在给定请求的响应头部可用时发送,在下载任何额外内容之前。
此信号的处理器可以通过引发
StopDownload
异常来停止正在进行中的响应下载。有关更多信息和示例,请参阅 停止响应下载 主题。此信号不支持其处理器返回 deferreds。