这些天一直在啃scrapy源码,总算初步掌握了其运行流程,打算把一些收获写下来,做个记录。
常用scrapy的朋友应该知道,spider、downloadmiddleware以及pipeline中经常使用from_crawler来传递参数,如下图:
这个crawler很好用,可以直接crawler.settings获得参数,也可以搭配信号使用,比如上图的spider_opened。
但这个crawler是怎么来的呢,其实就是传参而已,只不过我们平常习惯使用构造方法_ init _,而这里是调用classmethod类方法。
上面这个函数的意思:①创建一个TempSpiderMiddleware类的实例s;②使用crawler实例的crawler.signals.connect方法将实例s的spider_opened方法与spider_opened信号绑定起来;③返回实例s
那么scrapy中是如何调用的呢
首先看spider,spider的初始化是在scrapy/crawler.py中的Crawler类中,实例化过程如下:
而这里的self.spidercls其实就是我们经常手写的spider,别忘了我们的spider是继承scrapy.Spider的,scrapy.Spider中实例化部分代码如下图:
从图中红框部分可以看到,其实我们手写的spider中也是可以直接用self.settings来调用参数的,是不是很方便,这些都是看了源码之后的收获(原谅我没好好看文档),表示时间没白花,哈哈。
剩下的middleware、pipeline,甚至扩展EXTENSIONS都是同样实例化的,而有意思的是,downloadmiddleware、pipeline,还有扩展EXTENSIONS的实例化Manager,都是继承scrapy.middleware下的MiddlewareManager。
在MiddlewareManager中,cls._get_mwlist_from_settings(settings)方法需要继承改写,作用是读取配置文件中所需模块的所在路径,并添加到列表中(这就是我们可以写很多个middleware或pipeline的原因),然后逐个通过load_object方法导入模块,再调用每个模块的from_crawler或from_settings方法,如下图: