栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

Scarpy源码分析4

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Scarpy源码分析4

2021SC@SDUSC

3.2 从入口开始分析

简单的认识了主要的几个类之后,我们来跟下代码。运行爬虫时,很多时候我们会这么执行

$ scrapy crawl 

看下这个 scrapy 可执行文件

#!/Users/kevinbai/.pyenv/versions/3.7.5/envs/site_analysis/bin/python3.7
# -*- coding: utf-8 -*-
import re
import sys

from scrapy.cmdline import execute

if __name__ == '__main__':
    sys.argv[0] = re.sub(r'(-script.pyw?|.exe)?$', '', sys.argv[0])
    sys.exit(execute())

PS:使用不同管理工具,可执行文件的路径有差别,上面的虚拟环境是由 pyenv 创建,你要根据自己的情况去找下。

原来就是调用 scrapy.cmdline.execute 方法

# scrapy/cmdline.py

def execute(argv=None, settings=None):
    ...
    cmd.crawler_process = CrawlerProcess(settings)
    _run_print_help(parser, _run_command, cmd, args, opts)
    sys.exit(cmd.exitcode)

这个方式是命令行的入口,根据项目配置做了一些基础的配置,并使用 CrawlerProcess 作为爬虫的执行环境。看下 crawl 命令

# scrapy/commands/crawl.py

class Command(ScrapyCommand):
    ...

    def run(self, args, opts):
        ...

        self.crawler_process.crawl(spname, **opts.spargs)
        self.crawler_process.start()

        if self.crawler_process.bootstrap_failed:
            self.exitcode = 1

这里调用了 CrawlerProcess 的 crawl 和 start 方法。先看下后者

# scrapy/crawler.py

class CrawlerProcess(CrawlerRunner):
    ...

    def start(self, stop_after_crawl=True):
        ...
        reactor.installResolver(self._get_dns_resolver())
        tp = reactor.getThreadPool()
        tp.adjustPoolsize(maxthreads=self.settings.getint('REACTOR_THREADPOOL_MAXSIZE'))
        reactor.addSystemEventTrigger('before', 'shutdown', self.stop)
        reactor.run(installSignalHandlers=False)  # blocking call

做了这么几件事

  • 自定义 DNS 解析器
  • 根据配置调整线程池,这个线程池将会用于解析 DNS,因为 Scrapy 解析 DNS 时,会用到 socket 库,只能使用多线程进行并发
  • 绑定回调,当程序要结束时停止当前运行的爬虫
  • 启动 reactor

至于爬虫是怎么创建的,引擎内部是怎么调度的,就要从 crawl 方法开始看了

# scrapy/crawler.py

class Crawler(object):
    ...

    @defer.inlineCallbacks
    def crawl(self, *args, **kwargs):
        assert not self.crawling, "Crawling already taking place"
        self.crawling = True

        try:
            self.spider = self._create_spider(*args, **kwargs)
            self.engine = self._create_engine()
            start_requests = iter(self.spider.start_requests())
            yield self.engine.open_spider(self.spider, start_requests)
            yield defer.maybeDeferred(self.engine.start)
        except Exception:
            ...
  • 首先是创建爬虫 spider
  • 然后将 spider 和初始请求的迭代器作为参数创建引擎 engine
  • 执行 engine 的 open_spider 方法并启动 engine

这部分代码我先不分析代码里面关于错误的解决,这有助于理解代码的核心思路。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/395999.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号