信号¶
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
延迟信号处理程序¶
一些信号支持从它们的处理程序中返回Deferred
或awaitable 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(),
}
内置信号参考¶
以下是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中删除项目后发送。此信号支持从其处理程序返回延迟对象。
项目错误¶
- scrapy.signals.item_error(item, response, spider, failure)¶
当Item Pipeline生成错误时(即引发异常)发送,除了
DropItem异常。此信号支持从其处理程序返回延迟对象。
- Parameters:
item (item object) – 在Item Pipeline中导致错误的项目
response (
Response|None) – 当异常被抛出时正在处理的响应,或者如果它是从start_requests()产生的,则为None。spider (
Spider对象) – 引发异常的爬虫失败 (twisted.python.failure.Failure) – 引发的异常
爬虫信号¶
spider_closed¶
- scrapy.signals.spider_closed(spider, reason)¶
在蜘蛛关闭后发送。这可以用于释放每个蜘蛛在
spider_opened上保留的资源。此信号支持从其处理程序返回延迟对象。
spider_opened¶
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:
失败 (twisted.python.failure.Failure) – 引发的异常
response (
Response对象) – 当异常被抛出时正在处理的响应spider (
Spider对象) – 引发异常的爬虫
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对象) – 生成请求的爬虫
请求被丢弃¶
请求到达下载器¶
request_left_downloader¶
接收的字节数¶
新版本2.2新增。
- scrapy.signals.bytes_received(data, request, spider)¶
当为特定请求接收到一组字节时,由HTTP 1.1和S3下载处理程序发送。对于同一请求,此信号可能会多次触发,每次都有部分数据。例如,对于25 kb的响应,可能的情况是触发两次信号,每次有10 kb的数据,最后一次有5 kb的数据。
此信号的处理程序可以通过引发
StopDownload异常来停止正在进行的响应下载。请参阅停止响应下载主题以获取更多信息和示例。此信号不支持从其处理程序返回延迟。
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对象) – 与响应关联的爬虫