这篇文章将简单介绍一下Scrapy的启动过程。Scrapy是如何启动的?
在Scrapy的Tutorial中使用了这样几行代码来启动爬虫:
from scrapy import cmdline
if __name__ == '__main__':
cmdline.execute("scrapy crawl tutorial".split())
这里看起来就是整个爬虫的入口了,我们看下cmdline的execute函数
def execute(argv=None, settings=None):
# ------------------------------------------------------------------
# 前面是一堆配置解析、生成环境、命令校验的代码,有兴趣的同学可以去看下
# ------------------------------------------------------------------
cmd = cmds[cmdname] # 命令实例,在本例为scrapy.commands.crawl.Command
parser.usage = "scrapy %s %s" % (cmdname, cmd.syntax())
parser.description = cmd.long_desc()
settings.setdict(cmd.default_settings, priority='command')
cmd.settings = settings
cmd.add_options(parser)
# ------------------------------------------------------------------
opts, args = parser.parse_args(args=argv[1:])
_run_print_help(parser, cmd.process_options, args, opts)
cmd.crawler_process = CrawlerProcess(settings) # 初始化爬虫
_run_print_help(parser, _run_command, cmd, args, opts)
sys.exit(cmd.exitcode)
代码比较长,省略了一些跟我们文章无关的代码。现在我们剩下的代码主要是做了一下几个工作:
- 生成一个Command实例(cmd)
- 生成一个CrawlerProcess类实例(A class to run multiple scrapy crawlers in a process simultaneously)
- 将CrawlerProcess类实例交给Command实例保管
- 调用
_run_print_help
方法
其中_run_print_help
函数如下:
def _run_print_help(parser, func, *a, **kw):
try:
func(*a, **kw)
except UsageError as e:
if str(e):
parser.error(str(e))
if e.print_help:
parser.print_help()
sys.exit(2)
可以看成函数的简单包装。源代码中第一个_run_print_help
方法是设置了日志相关配置,这里就不看了。第二个_run_print_help
方法真正启动了爬虫
cmd.crawler_process = CrawlerProcess(settings) # 初始化爬虫
_run_print_help(parser, _run_command, cmd, args, opts)
其中_run_command
是根据环境对cmd.run(args, opts)
的包装,我们直接看cmd.run(args, opts)
。前面省略掉的代码已经根据输入的命令(scrapy crawl tutorial)匹配出,我们正在调用的是scrapy.commands.crawl.Command这个类的方法,去看该类的run方法:
def run(self, args, opts):
if len(args) < 1:
raise UsageError()
elif len(args) > 1:
raise UsageError("running 'scrapy crawl' with more than one spider is no longer supported")
spname = args[0]
self.crawler_process.crawl(spname, **opts.spargs)
self.crawler_process.start()
开始是入参校验,spname就是你爬虫的名字,本例中为tutorial,CrawlerProcess是可以处理多爬虫的,所以这里指定你要启动爬虫的名字,配置,然后开爬。在这里,crawler_process.crawl(spname, **opts.spargs)
该方法初始化了Spider、Engine等组件,并让Scheduler开始调度(如我们熟知的几大组件)。crawler_process.start()
方法开启了Twisted::reactor事件中心,实现异步爬取。这些我们放在下一篇讲。