Scrapy数据流转分析(二)

这篇文章将简单介绍一下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)

代码比较长,省略了一些跟我们文章无关的代码。现在我们剩下的代码主要是做了一下几个工作:

  1. 生成一个Command实例(cmd)
  2. 生成一个CrawlerProcess类实例(A class to run multiple scrapy crawlers in a process simultaneously)
  3. 将CrawlerProcess类实例交给Command实例保管
  4. 调用_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事件中心,实现异步爬取。这些我们放在下一篇讲。

你可能感兴趣的:(Scrapy数据流转分析(二))