在同个项目下写了多个爬虫之后,如果我们需要同时并行运行多个爬虫,需要怎么做呢?
关于这个,我找到了两篇可以解决问题的博文,主要思路是在爬虫目录下新建commands目录,重新定义Command函数,通过这个思路,我们可以做到的是重新定义启动爬虫时的命令行参数,收集我们需要传入内部的参数,并且再通过Command函数解析,并传递给每个运行的爬虫。
其中一篇博文解释的思路比较清晰,耐心读就可以读懂:https://blog.csdn.net/qq_38282706/article/details/80991196?utm_source=blogxgwz3,其中评论中提供了一种方法,结合了add_option(自定义参数)的功能和我们一般对单个爬虫用到的通过爬虫内部__init__()函数添加参数的方法,绕过了将值赋给setting再在pipeline中使用的步骤。
另一篇博文则比较详细地描述了结合自定义config文件设置scrapy参数的方法,如果我们希望引入自己的config文件的话,还是很有参考价值的。
本次我的代码主要涉及到三个文件:与spiders文件夹同目录的config1文件,与spiders文件夹同目录的settings.py文件,与spiders文件夹同目录的commands文件夹下的comd.py文件
首先,这次我用到的配置文件格式是ini类型的标准格式,这样可以很方便地在脚本中调用python的configparser这个库,通过简单的操作就可以对内容进行解析,这个库的具体使用可以在这篇博文找到:https://www.cnblogs.com/plf-Jack/p/11170284.html,与字典调用很类似。这里我的配置文件内容如下:
[tmp]
keywords=电网,停电
pages=2
[baijiahao]
keywords=电网,停电
pages=2
[sinanews]
keywords=电网,停电
pages=2
因为我没有找到如何在ini文件中表示列表,这里索性直接传入字符串,在传入爬虫后通过split()进行解析,得到关键词列表。
在最主要的comd.py文件中,我采用了较为简单的方法,没有修改pipeline,而是基于之前对单个爬虫使用如下命令行命令时对每个spider函数进行的修改:
#此前通过命令行运行单个爬虫,并传入参数时的命令
scrapy crawl tmp -a keywords=电网,停电 -a pages=2
#spiders带参数初始化
class SinanewsSpider(scrapy.Spider):
#......
def __init__(self, keywords=None, pages=1, *args, **kwargs):
super(SinanewsSpider, self).__init__(*args, **kwargs)
self.keys=keywords.split(',')
self.page = int(pages)
#......
下面贴上comd.py
import os
from scrapy.commands import ScrapyCommand
from scrapy.utils.conf import arglist_to_dict
from scrapy.utils.python import without_none_values
from scrapy.exceptions import UsageError
import configparser
import scrapy.commands.crawl as crawl
class Command(crawl.Command):
requires_project = True
def syntax(self):
'''
此处通过运行本程序运行所有爬虫,因此不必提供spider的名字
:return:
'''
return "[options]"
def short_desc(self):
return "Run all spider"
def add_options(self, parser):
ScrapyCommand.add_options(self, parser)
parser.add_option("-a", dest="spargs", action="append", default=[], metavar="NAME=VALUE",
help="set spider argument (may be repeated)")
parser.add_option("-o", "--output", metavar="FILE",
help="dump scraped items into FILE (use - for stdout)")
parser.add_option("-t", "--output-format", metavar="FORMAT",
help="format to use for dumping items with -o")
#添加配置文件的名称,其中dest的值Conf可以在run函数中使用opts.Conf调用
parser.add_option("-c", "--config-file", dest="Conf",
help="config file path")
def run(self, args, opts):
#获取comd.py的当前目录
current_path = os.path.dirname(os.path.abspath(__file__))
configpath = opts.Conf
#合成config文件的地址
conf_path = os.path.join(os.path.dirname(current_path), configpath)
cf = configparser.ConfigParser()
cf.read(conf_path, encoding="utf-8")
#获得项目下所有爬虫列表
spider_list = self.crawler_process.spiders.list()
for spid in spider_list:
keywords = cf.get(spid, 'keywords')
pages = cf.get(spid, 'pages')
#对每个爬虫传入其需要的参数
self.crawler_process.crawl(spid, keywords=keywords, pages=pages, **opts.spargs)
# keywords = cf.get('baijiahao', 'keywords')
# pages = cf.get('baijiahao', 'pages')
# self.crawler_process.crawl('baijiahao', keywords=keywords, pages=pages, **opts.spargs)
self.crawler_process.start()
需要注意的是syntax函数return的内容有一些修改,因为我们要运行本项目所有爬虫,因此不必提供spider的名字。
最后需要在settings.py文件中进行配置:
#COMMANDS_MODULE ='项目名.comd所在的目录名'
COMMANDS_MODULE = 'baiduCrawler.commands'
接下来,只需要运行以下命令,就可以并行地运行多个爬虫了!
scrapy comd -c config1