信号
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 objects,允许您运行不阻塞 Scrapy 的异步代码。如果信号处理程序返回其中一个对象,Scrapy 会等待该异步操作完成。
让我们来看一个使用协程的例子
import scrapy
import treq
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 objects。
内置信号参考
以下是 Scrapy 内置信号及其含义的列表。
引擎信号
engine_started
注意
此信号可能会在 spider_opened 信号*之后*触发,具体取决于爬虫的启动方式。因此,**不要**依赖此信号在 spider_opened 之前触发。
engine_stopped
scheduler_empty
- scrapy.signals.scheduler_empty()
每当引擎从调度器请求待处理的请求(即调用其
next_request()方法)并且调度器返回空时发送。有关示例,请参阅延迟启动请求迭代。
此信号不支持异步处理程序。
项信号
注意
由于最多有 CONCURRENT_ITEMS 个项目并行处理,许多延迟操作会使用 DeferredList 同时触发。因此,下一批会等待 DeferredList 触发,然后为下一批抓取的项目运行相应的项信号处理程序。
item_scraped
item_dropped
item_error
爬虫信号
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')代码的理想位置。此信号不支持异步处理程序。
- 参数:
spider (
Spider对象) – 进入空闲状态的爬虫
注意
在您的
spider_idle处理程序中调度一些请求**不能**保证可以阻止爬虫被关闭,尽管有时可以。这是因为如果所有调度的请求都被调度器拒绝(例如,因重复而被过滤),爬虫可能仍会保持空闲状态。
spider_error
- scrapy.signals.spider_error(failure, response, spider)
当爬虫回调函数产生错误(即抛出异常)时发送。
此信号不支持异步处理程序。
- 参数:
failure (twisted.python.failure.Failure) – 抛出的异常
response (
Response对象) – 抛出异常时正在处理的响应spider (
Spider对象) – 抛出异常的爬虫
feed_slot_closed
- scrapy.signals.feed_slot_closed(slot)
当Feed Exports槽关闭时发送。
此信号支持异步处理程序。
- 参数:
slot (scrapy.extensions.feedexport.FeedSlot) – 已关闭的槽
feed_exporter_closed
- scrapy.signals.feed_exporter_closed()
当Feed Exports扩展关闭时发送,在扩展处理
spider_closed信号期间,在所有 Feed 导出处理完毕之后。此信号支持异步处理程序。
memusage_warning_reached
- scrapy.signals.memusage_warning_reached()
当内存使用量达到警告阈值 (
MEMUSAGE_WARNING_MB) 时,由MemoryUsage扩展发送。此信号不支持异步处理程序。
请求信号
request_scheduled
- scrapy.signals.request_scheduled(request, spider)
当引擎被要求调度一个
Request以供稍后下载时发送,在请求到达调度器之前。抛出
IgnoreRequest以在请求到达调度器之前将其丢弃。此信号不支持异步处理程序。
2.11.2 版新增:允许使用
IgnoreRequest丢弃请求。
request_dropped
request_reached_downloader
request_left_downloader
bytes_received
- scrapy.signals.bytes_received(data, request, spider)
当 HTTP 1.1 和 S3 下载处理程序收到针对特定请求的一组字节时发送。此信号可能会针对同一请求多次触发,每次都带有部分数据。例如,一个 25 kb 响应的可能情况是两次触发 10 kb 数据的信号,最后一次触发 5 kb 数据的信号。
此信号的处理程序可以通过抛出
StopDownload异常来停止正在进行的响应下载。有关更多信息和示例,请参阅停止响应下载主题。此信号不支持异步处理程序。
headers_received
- scrapy.signals.headers_received(headers, body_length, request, spider)
当 HTTP 1.1 和 S3 下载处理程序收到给定请求的响应头,并在下载任何额外内容之前发送。
此信号的处理程序可以通过抛出
StopDownload异常来停止正在进行的响应下载。有关更多信息和示例,请参阅停止响应下载主题。此信号不支持异步处理程序。