关于Python中Scrapy框架signals的用法请教

看了 scrapy 的官方文档,关于 signals 的函数在 from_crawler()中有如下示例代码:

crawler.signals.connect(ext.spider_opened, signal=signals.spider_opened) #代码 1 
crawler.signals.connect(ext.spider_closed, signal=signals.spider_closed) #代码 2  

对应两个方法定义如下: def spider_opened(self, spider): spider.log(“opened spider %s” % spider.name) def spider_closed(self, spider): spider.log(“closed spider %s” % spider.name)

恳请大家指点,上面代码中和 signals 的这几个函数和方法到底是完成了什么工作呢? 谢谢!


关于Python中Scrapy框架signals的用法请教

4 回复

主要是写 extension 用的, 配合几个 signal 当触发器用的, 具体可以看看内置的 extension 代码


Scrapy的signals机制是框架的核心扩展点,让你能在爬虫生命周期中插入自定义逻辑。它基于pydispatch实现,通过信号/槽机制工作。

最常用的几个信号:

  • engine_started/engine_stopped:引擎启动/停止时触发
  • spider_opened/spider_closed:爬虫打开/关闭时触发
  • item_scraped:item被抓取后触发
  • request_scheduled/response_received:请求调度和响应接收时触发

基本用法示例:

from scrapy import signals
from scrapy.crawler import Crawler

class MySpider(scrapy.Spider):
    name = 'example'
    
    @classmethod
    def from_crawler(cls, crawler, *args, **kwargs):
        spider = super().from_crawler(crawler, *args, **kwargs)
        # 连接信号处理器
        crawler.signals.connect(spider.spider_opened, signal=signals.spider_opened)
        crawler.signals.connect(spider.spider_closed, signal=signals.spider_closed)
        crawler.signals.connect(spider.item_scraped, signal=signals.item_scraped)
        return spider
    
    def spider_opened(self, spider):
        print(f"爬虫 {spider.name} 启动了")
    
    def spider_closed(self, spider):
        print(f"爬虫 {spider.name} 关闭了")
    
    def item_scraped(self, item, response, spider):
        print(f"抓到item: {item}")
    
    def start_requests(self):
        yield scrapy.Request('http://example.com', callback=self.parse)
    
    def parse(self, response):
        yield {'title': response.css('title::text').get()}

也可以在扩展(Extension)中使用:

from scrapy import signals
from scrapy.exceptions import NotConfigured

class StatsExtension:
    def __init__(self, stats):
        self.stats = stats
        self.item_count = 0
    
    @classmethod
    def from_crawler(cls, crawler):
        ext = cls(crawler.stats)
        crawler.signals.connect(ext.spider_opened, signal=signals.spider_opened)
        crawler.signals.connect(ext.item_scraped, signal=signals.item_scraped)
        return ext
    
    def spider_opened(self, spider):
        self.stats.set_value('start_time', time.time())
    
    def item_scraped(self, item, response, spider):
        self.item_count += 1
        self.stats.set_value('items_scraped', self.item_count)

关键点:信号处理器接收的参数由具体信号决定,需要查看Scrapy文档确认。比如item_scraped接收(item, response, spider)三个参数,而spider_opened只接收(spider)一个参数。

信号机制让Scrapy的扩展性很强,但别滥用,过度使用会影响性能。

总结:用from_crawler连接信号,根据需求选择合适的信号点。

这里首先注册两个函数 spider_opened, spider_closed。当 spider 启动和关闭的时候会触发。有点类似 wrapper 的概念
比如爬虫结束可以执行一些清理的工作比如发邮件。


非常感谢!!!

回到顶部