Scrapy中扩展(Extension)的定义

Scrapy扩展是通过在项目中捕捉一些信号来完成额外的工作或添加额外的功能。

先看一个例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class MyCustomStatsExtension(object):
"""
这个extension专门用来定期搜集一次stats
"""
def __init__(self, stats):
self.stats = stats
self.time = 60.0

@classmethod
def from_crawler(cls, crawler, *args, **kwargs):
instance = cls(crawler.stats)
crawler.signals.connect(instance.spider_opened, signal=signals.spider_opened)
crawler.signals.connect(instance.spider_closed, signal=signals.spider_closed)
return instance

def spider_opened(self):
self.tsk = task.LoopingCall(self.collect)
self.tsk.start(self.time, now=True)

def spider_closed(self):
if self.tsk.running:
self.tsk.stop()

def collect(self):
#这里收集stats并写入相关的储存。
#目前展示是输出到终端
print u'将展示收集到的数据'
print self.stats.get_stats()

解释

Scrapy API的主要入口是 Crawler 的实例对象, 通过类方法 from_crawler 将它传递给扩展(extensions),详细解释参见这里

所以第一步通过from_crawler类方法获取到Crawler对象。

1
2
3
4
5
6
@classmethod
def from_crawler(cls, crawler, *args, **kwargs):
instance = cls(crawler.stats)
crawler.signals.connect(instance.spider_opened, signal=signals.spider_opened)
crawler.signals.connect(instance.spider_closed, signal=signals.spider_closed)
return instance
  • 我的理解是当项目启动后就开启了一个抓取的行为这个行为通过Crawler对象来管理,表现为对spider的控制和状态指示。

之后通过from_crawler类方法获取的crawler注册信号处理方法:

1
2
crawler.signals.connect(instance.spider_opened, signal=signals.spider_opened)
crawler.signals.connect(instance.spider_closed, signal=signals.spider_closed)

这里对应的信号spider_opened注册为instancespider_opened方法,信号spider_closed注册为instancespider_closed方法。

  • spider_opened 信号在爬虫开启时由spider发送。
  • spider_closed 信号在爬虫结束时由spider发送。

而 instance 是通过instance = cls(crawler.stats)实例化的本扩展的一个实例。作用在于将crawler.stats传递给本扩展,并暴露自己的方法用于crawler信号的注册。

这样启动项目后spider发送spider_opened信号,本扩展会接收到这个信号执行绑定的spider_opened方法:

1
2
3
def spider_opened(self):
self.tsk = task.LoopingCall(self.collect)
self.tsk.start(self.time, now=True)

通过这个方法打开一个定时任务,间隔60秒执行一次本扩展的collect方法打印spider的状态:

1
2
3
4
5
def collect(self):
#这里收集stats并写入相关的储存。
#目前展示是输出到终端
print u'将展示收集到的数据'
print self.stats.get_stats()

同理,spider关闭后,扩展接收到spider_closed信号,执行本扩展的spider_closed方法关闭这个定时任务。

1
2
3
def spider_closed(self):        
if self.tsk.running:
self.tsk.stop()
坚持原创技术分享,您的支持将鼓励我继续创作!