Scrapy中如何从单个类实例化多个爬虫?
用单个Scrapy类实例化多个爬虫的解决方案
嗨,我之前也尝试过用这种方式减少重复代码,确实能在大型项目里省不少事!Scrapy虽然没把这种做法写进官方标准流程,但完全是可行的,你跑不起来大概率是因为没处理好父类初始化和爬虫注册的细节。下面给你一步步拆解解决方法:
1. 正确重写爬虫类的__init__方法
首先,CrawlSpider本身有自己的初始化逻辑(比如处理规则、域名这些),你自定义的__init__必须先调用父类的初始化方法,不然会丢失Scrapy内置的核心功能。另外注意参数名的拼写——你代码里的starturls应该是start_urls,这是Scrapy识别的标准参数名。
给你一个修正后的示例:
from scrapy.spiders import CrawlSpider, Rule from scrapy.linkextractors import LinkExtractor class ExampleSpider(CrawlSpider): def __init__(self, name, source, allowed_domains, start_urls, *args, **kwargs): # 必须先调用父类的初始化,传入Scrapy需要的核心参数 super().__init__(name=name, allowed_domains=allowed_domains, start_urls=start_urls, *args, **kwargs) self.source = source # 保存自定义的source标识,方便后续解析区分 # 如果需要根据不同source设置不同爬取规则,也可以在这里动态定义 self.rules = ( Rule(LinkExtractor(allow=r'content/'), callback='parse_item', follow=True), ) # 动态修改rules后,必须调用这个方法让规则生效 self.compile_rules() def parse_item(self, response): # 这里可以用self.source来区分不同爬虫实例的输出 item = { 'source': self.source, 'url': response.url, 'title': response.css('h1::text').get() } return item
2. 实例化多个爬虫的正确姿势
Scrapy默认会扫描spiders目录下的爬虫类并实例化,但我们需要主动注册多个不同配置的实例。可以在spiders目录下创建一个工厂文件(比如spider_factory.py),批量生成爬虫实例:
from .example_spider import ExampleSpider # 定义所有爬虫的配置,每个配置对应一个实例 SPIDER_SETTINGS = [ { 'name': 'tech_spider', 'source': 'tech_website', 'allowed_domains': ['tech-example.com'], 'start_urls': ['https://tech-example.com/latest'] }, { 'name': 'fashion_spider', 'source': 'fashion_website', 'allowed_domains': ['fashion-example.com'], 'start_urls': ['https://fashion-example.com/trends'] } ] # 循环实例化每个爬虫,Scrapy会自动识别这些实例 for config in SPIDER_SETTINGS: ExampleSpider(**config)
3. 启动爬虫的两种方式
- 单独启动某个爬虫:直接用Scrapy命令行,指定实例的name即可:
scrapy crawl tech_spider - 同时启动多个爬虫:如果需要一次性跑所有实例,可以写一个自定义启动脚本(比如
run_spiders.py):
然后直接运行这个脚本就能同时启动多个爬虫了。from scrapy.crawler import CrawlerProcess from scrapy.utils.project import get_project_settings from spiders.example_spider import ExampleSpider settings = get_project_settings() process = CrawlerProcess(settings) # 逐个添加爬虫实例 process.crawl(ExampleSpider, **{ 'name': 'tech_spider', 'source': 'tech_website', 'allowed_domains': ['tech-example.com'], 'start_urls': ['https://tech-example.com/latest'] }) process.crawl(ExampleSpider, **{ 'name': 'fashion_spider', 'source': 'fashion_website', 'allowed_domains': ['fashion-example.com'], 'start_urls': ['https://fashion-example.com/trends'] }) process.start()
常见坑点提醒
- 一定要调用
super().__init__:跳过这一步会导致Scrapy无法识别爬虫的基本配置,直接报错。 - 爬虫name必须唯一:每个实例的name参数不能重复,否则Scrapy会认为是同一个爬虫,只会启动一个。
- 动态修改rules后要调用
compile_rules():如果在__init__里重新定义了rules,必须调用这个方法让规则生效,否则爬取时不会执行规则逻辑。
这种方式在维护多个相似逻辑的爬虫时特别好用,能大幅减少重复代码,放心用就行~
内容的提问来源于stack exchange,提问作者NFB
相关产品推荐
相关产品推荐

