Scrapy:爬行多个蜘蛛共享相同的项目,管道和设置,但具有单独的输出

时间:2017-07-25 16:44:27

标签: python web-scraping scrapy scrapy-spider

我正在尝试使用基于官方文档中提供的代码的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>

感谢您的帮助!

3 个答案:

答案 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()