我正在尝试使用基于官方文档中提供的代码的Python脚本运行多个蜘蛛。我的scrapy项目包含多个蜘蛛( Spider1,Spider2,等),它们抓取不同的网站并将每个网站的内容保存在不同的JSON文件中( output1。 json,output2.json,等)。
在不同网站上收集的项目共享相同的结构,因此蜘蛛使用相同的项目,管道和设置类。输出由管道中的自定义JSON类生成。
当我单独运行蜘蛛时,它们会按预期工作,但是当我使用下面的脚本从scrapy API运行蜘蛛时,项目会在管道中混合。 Output1.json 应仅包含 Spider1 抓取的项目,但它还包含 Spider2 的项目。如何使用scrapy API使用相同的项目,管道和设置爬行多个蜘蛛,但生成单独的输出?
以下是我用来运行多个蜘蛛的代码:
import scrapy
from scrapy.crawler import CrawlerProcess
from web_crawler.spiders.spider1 import Spider1
from web_crawler.spiders.spider2 import Spider2
settings = get_project_settings()
process = CrawlerProcess(settings)
process.crawl(Spider1)
process.crawl(Spider2)
process.start()
示例output1.json:
{
"Name": "Thomas"
"source": "Spider1"
}
{
"Name": "Paul"
"source": "Spider2"
}
{
"Name": "Nina"
"source": "Spider1"
}
示例output2.json:
{
"Name": "Sergio"
"source": "Spider1"
}
{
"Name": "David"
"source": "Spider1"
}
{
"Name": "James"
"source": "Spider2"
}
通常,spider1(“source”:“Spider1”)抓取的所有名称都应该在output1.json中,而spider2(“source”:“Spider2”)抓取的所有名称都应该在output2.json < / p>
感谢您的帮助!
答案 0 :(得分:2)
第一个问题是蜘蛛在同一个过程中运行。通过链接延迟来顺序运行蜘蛛解决了这个问题:
#scrapy
from twisted.internet import reactor, defer
from scrapy.crawler import CrawlerRunner
from scrapy.utils.project import get_project_settings
from scrapy.utils.log import configure_logging
#spiders
from web_crawler.spiders.spider1 import Spider1
from web_crawler.spiders.spider2 import Spider2
configure_logging()
settings = get_project_settings()
runner = CrawlerRunner(settings)
@defer.inlineCallbacks
def crawl():
yield runner.crawl(Spider1)
yield runner.crawl(Spider2)
reactor.stop()
crawl()
reactor.run()
我的管道中还有第二个错误:当close_spider时,我没有清除我的结果列表。因此,spider2正在将项目添加到已包含spider1项目的列表中。
class ExportJSON(object):
results = []
def process_item(self, item, spider):
self.results.append(dict(item))
return item
def close_spider(self, spider):
file = open(file_name, 'w')
line = json.dumps(self.results)
file.write(line)
file.close()
self.results.clear()
谢谢!
答案 1 :(得分:0)
根据docs按顺序在同一进程上运行蜘蛛,您必须链接deferreds。
试试这个:
import scrapy
from scrapy.crawler import CrawlerRunner
from web_crawler.spiders.spider1 import Spider1
from web_crawler.spiders.spider2 import Spider2
settings = get_project_settings()
runner = CrawlerRunner(settings)
@defer.inlineCallbacks
def crawl():
yield runner.crawl(Spider1)
yield runner.crawl(Spider2)
reactor.stop()
crawl()
reactor.run()
答案 2 :(得分:0)
更好的解决方案是(如果你有多个蜘蛛)它动态地获取蜘蛛并运行它们。
from scrapy import spiderloader
from scrapy.utils import project
from twisted.internet.defer import inlineCallbacks
@inlineCallbacks
def crawl():
settings = project.get_project_settings()
spider_loader = spiderloader.SpiderLoader.from_settings(settings)
spiders = spider_loader.list()
classes = [spider_loader.load(name) for name in spiders]
for my_spider in classes:
yield runner.crawl(my_spider)
reactor.stop()
crawl()
reactor.run()