Scrapy 中很多组件都有 from_crawler()方法,下面是我读源码后对 from_crawler()方法的理解,记录下来。
from_crawler() 方法一般用传入的参数来实例化一个对象,比如 scrapy.spider 中的 from_crawler():
@classmethod
def from_crawler(cls, crawler, *args, **kwargs):
spider = cls(*args, **kwargs) # 第一步:携带参数实例化这个类
spider._set_crawler(crawler) # 第二步:将 crawler 传递给实例,使新实例有crawler属性和settings参数
return spider # 返回类的实例对象
然后再 scrapy.crawler.Crawler._create_spider() 中调用:
def _create_spider(self, *args, **kwargs):
return self.spidercls.from_crawler(self, *args, **kwargs)
spider 中的 from_crawler() 比较就是最浅显易懂的例子,但也包含最核心的两步:
(1) 用携带的参数来实例化类,一般用 cls();
(2)将crawler 传递给新创建的实例,使新实例有 crawler 的属性和 settings 配置的参数。
各个组件是如何调用 from_crawler()方法的呢?下面以 scheduler 为例子:
scrapy.core.engine.ExecutionEngine.open_spider() 中,调用了 scheduler 的 from_crawler()方法来生成 scheduler
scheduler = self.scheduler_cls.from_crawler(self.crawler)
因为,这是 ExecutionEngine 的方法调用的,所以参数 "self.crawler" 中的 self 是 ExecutionEngine,而 ExecutionEngine 是 scrapy.crawler.Crawler._create_engine() 方法创建的:
# Crawler 中 ExecutionEngine 对象的创建
def _create_engine(self):
return ExecutionEngine(self, lambda _: self.stop()) # crawler将self对象传入创建ExecutionEngine
所以传入 from_crawler(self.crawler) 的 self.crawler 就是 scrapy.crawler.Crawler 对象。
总结一下:
from_crawler() 用于根据传入的参数和 crawler 对象来生成 scheduler,使得scheduler有crawler的属性和配置。