scrapy中settings参数的使用详解

scrapy中settings参数的使用详解

代码开发的时候,总是提倡一些参数写在配置文件中,这对于未来的代码管理、维护、测试、部署都有很大的益处。
scrapy作为一个强大爬虫的框架,其settings的应用机制也十分健壮,在这我总结了一些平时在爬虫项目中配置参数的使用技巧。


settings的优先级

官方文档中scrapy中settings参数有四个级别:

  1. 命令行选项(Command line Options)(最高优先级)
  2. 项目设定模块(Project settings module)
  3. 命令默认设定模块(Default settings per-command)
  4. 全局默认设定(Default global settings) (最低优先级)


其实我们平时使用的时候,settings配置主要就在这三个地方进行:

1.命令行选项:

所谓的命令行选项,就是我们平时使用命令行scrapy crawl somespider时,可在命令行后面添加的自定义参数。

例如: scrapy crawl somespider -s LOG_FILE=test.log -s MACHINE_NAME=123 -s ITEM_PIPELINES={}

在上面的命令中,我们在启动somespider这个spider的时候,就设置了LOG_FILE为test.log, 自定义了一个变量MACHINE_NAME为123,将ITEM_PIPELINES设置为空。

命令行选项是所有settings中优先级最高的(当然你写死在spider中的参数除外)


2.custom_settings:

custom_settings可以理解为spider的个性设置,通常我们在一个项目目录下会有很多个spider,但是只有一个settings.py全局配置文件,为了让不同的spider应用不同的设置,我们可以在spider代码中加入custom_settings设置。

例如:

spiders/somespider.py

from ..custom_settings import *

class Spider1(CrawlSpider):
    name = "spider1"
    custom_settings = custom_settings_for_spider1
    pass

class Spider2(CrawlSpider):
    name = "spider2"
    custom_settings = custom_settings_for_spider2
 

custom_settings.py

custom_settings_for_spider1 = {
    'LOG_FILE': 'spider1.log',
    'CONCURRENT_REQUESTS': 100,
    'DOWNLOADER_MIDDLEWARES': {
        'spider.middleware_for_spider1.Middleware': 667,
    },
    'ITEM_PIPELINES': {
        'spider.mysql_pipeline_for_spider1.Pipeline': 400,
    },
}

custom_settings_for_spider2 = {
    'LOG_FILE': 'spider2.log',
    'CONCURRENT_REQUESTS': 40,
    'DOWNLOADER_MIDDLEWARES': {
        'spider.middleware_for_spider2.Middleware': 667,
    },
    'ITEM_PIPELINES': {
        'spider.mysql_pipeline_for_spider2.Pipeline': 400,
    },
}

在spider里有两个蜘蛛spider1、spider2里,我们引入了来自custom_settings的配置变量custom_settings_for_spider1、custom_settings_for_spider2,通过这些变量,我们分别对两个爬虫的log文件、并发数、应用的中间件和管道文件进行了设置。

custom_settings的优先级在命令行以下,比settings.py要高。


3.settings.py:

settings.py是爬虫项目的配置文件,通常我们在一个项目目录下会有很多个spider,但是只有一个settings.py全局配置文件,在这个settings.py我们可以设置项目下所有爬虫的一些公共变量,例如用什么请求头、用哪种schedule,什么样的去重方式、甚至公共的数据库连接都可以写在settings.py文件里,settings.py的优先级是比较低的,次于命令行变量和custom_settings变量。


通过settings的设置,scrapy在crawler运行spider的时候,就会按照优先级把spider对应的设置用最高优先级的进行填充,这时候你可以在代码中从crawler.settings中获取到相应的设置。


settings的使用方法

说到settings里参数的使用方式,在最早写scrapy的时候,我时常都是在文件头里用

    from ..settings import *

这种方式来从settings里引入参数,这种方式最大的缺点是只能引入settings.py中的变量,如果你设置了更高级的命令行变量或者custom_settings变量,就引入不了了。

后来看多了源码,发现在spider类、middleware类、pipeline类以及extension等地方,都有一个from_crawler方法,通过这个方法能够从crawler.settiings中读取真正最高优先级的settiings(crawler中的settings可以理解为按优先级顺序从所有设置文件中读取到最高优先级的设置参数),这才是settings配置的正确引用方式。

话不多少,举几个例子:

在spiders中读取设置

spiders/spider.py

class spider1(CrawlSpider):

    name = "spider1"
    custom_settings = custom_settings_for_spider1

    def __init__(self):
        pass

    @classmethod
    def from_crawler(cls, crawler, *args, **kwargs):
        spider = super(spider1, cls).from_crawler(crawler, *args, **kwargs)
        machine_name = crawler.settings.get(
            'MACHINE_NAME', '')
        spider.machine = process_name
        return spider

在spider中,我用from_crawler方法从crawler的settings引入了一个变量MACHINE_NAME,这个变量可能来自于三个地方。

  1. 命令行:例如通过scrapy crawl somespider -s MACHINE_NAME=123来传入
  2. custom_settings:例如通过将custom_settings_for_spider1设置为{'MACHINE_NAME':123}来传入
  3. settings.py:可在settings.py中指定MACHINE_NAME=123来设置。


类似的我们看看中间件及管道中怎么读取设置。

在middleware中读取设置:

middleware_for_spider1.py

class Middleware(object):

    def __init__(self, headers):
        self.headers = headers

    @classmethod
    def from_crawler(cls, crawler):
        settings = crawler.settings
        headers= settings.getint('HEADERS')
        return cls(maxdepth, headers)

一个很简单的中间件,实现的是从crawler的设置中读入headers,并初始化中间件的headers值。

在pipeline中读取设置:

mysql_pipeline_for_spider1.py

class Pipeline(object):

    def __init__(self, mysql_settings):
        self.db = adbapi.ConnectionPool('pymysql',**mysql_settings)

    @classmethod
    def from_crawler(cls, crawler):
        settings = crawler.settings
        mysql_settings= settings.get('MYSQL_SETTINGS')
        return cls(mysql_settings)

一个很简单的管道文件,实现的是从crawler的设置中读入mysql设置,并初始化数据库连接。


特别值得注意的是,在spider中from_crawler方法调用是在spider类实例化以后,而在中间件,管道及拓展中,from_crawler方法调用是在相应的类实例化以前,在使用上要做区分。


settings的使用技巧

在这简单说说我在工作中对于不同类型settings的使用技巧吧。

1.首先是settings.py文件,在一个scrapy项目中,一些通用的设置,比如请求头、代理入口、数据库连接等等,都可以统一写在settings.py中。

2.其次是custom_settings,我一般会在scrapy项目中单独建立一个custom_settings.py文件,依据不同spider所需要的设置,比如某站点A可能反爬严,我并发设置短点,站点B没反爬,我并发设置高点;又或者A用了中间件MA,B用了中间件MB等,我在custom_settings.py文件中分别给予设置。

3.最后是命令行,都知道scrapy是协程,其不能完全利用好多核的计算机资源,所以我经常在一台机器上开多个scrapy进程,每个进程又对应相同的spider,对于这些进程如何进行管理,例如我要每个进程的日志分别查看,或者追踪每个进程的爬取速度等,这用命令行参数就比较合适。例如:

start_process1.py

from scrapy import cmdline

cmdline.execute('scrapy crawl spider1-s LOG_FILE=p1.log -s PROCESS_NAME=1'.split())

start_process2.py

from scrapy import cmdline

cmdline.execute('scrapy crawl spider1-s LOG_FILE=p2.log -s PROCESS_NAME=2'.split())

这样我就可以将相同spider的多个进程日志输出到不同log文件,并在程序内标记不同的process_name,为添加爬虫监控的钩子添加便利。


总结来说,就是同一个项目下的公共设置,我们写在settings.py文件里;不同爬虫的个性设置,我们写在custom_settings里;最后相同爬虫不同进程之间的一些设置,我们可以用命令行来进行设置。

编辑于 2018-02-27

文章被以下专栏收录