从Python脚本调用scrapy时未生成JSON输出文件

3 投票
2 回答
2707 浏览
提问于 2025-04-17 19:32

这是我用来调用Scrapy的Python脚本,关于这个问题的答案可以在这里找到:

从脚本调用Scrapy时,总是会在抓取后阻塞脚本执行

def stop_reactor():
    reactor.stop()
dispatcher.connect(stop_reactor, signal=signals.spider_closed)
spider = MySpider(start_url='abc')
crawler = Crawler(Settings())
crawler.configure()
crawler.crawl(spider)
crawler.start()
log.start()
log.msg('Running reactor...')
reactor.run()  # the script will block here until the spider is closed
log.msg('Reactor stopped.')

这是我的pipelines.py代码

from scrapy import log,signals
from scrapy.contrib.exporter import JsonItemExporter
from scrapy.xlib.pydispatch import dispatcher

class scrapermar11Pipeline(object):


    def __init__(self):
        self.files = {}
        dispatcher.connect(self.spider_opened , signals.spider_opened)
        dispatcher.connect(self.spider_closed , signals.spider_closed)


    def spider_opened(self,spider):
        file = open('links_pipelines.json' ,'wb')
        self.files[spider] = file
        self.exporter = JsonItemExporter(file)
        self.exporter.start_exporting()

    def spider_closed(self,spider):
       self.exporter.finish_exporting()
       file = self.files.pop(spider)
       file.close()

    def process_item(self, item, spider):
        self.exporter.export_item(item)
        log.msg('It reached here')
        return item

这段代码是从这里获取的:

Scrapy :: JSON导出问题

当我这样运行爬虫时:

scrapy crawl MySpider -a start_url='abc'

会生成一个包含预期输出的链接文件。但是当我执行这个Python脚本时,并没有创建任何文件,尽管爬虫运行正常,因为输出的Scrapy统计信息和上次运行的相似。我觉得Python脚本里可能有错误,因为在第一种方法中文件是被创建的。我该如何让脚本输出文件呢?

2 个回答

-1

对我来说,一个有效的解决方案是放弃运行脚本和内部API,改用命令行和GNU Parallel来实现并行处理。

如果想要在每个核心上运行所有已知的爬虫,可以这样做:

scrapy list | parallel --line-buffer scrapy crawl

scrapy list 命令会把所有爬虫列出来,每个爬虫占一行,这样我们就可以把它们作为参数传递给一个命令(scrapy crawl),然后交给GNU Parallel来处理。--line-buffer 这个选项的意思是,来自各个进程的输出会混合在一起打印到标准输出,但会按行显示,而不是把四分之一或二分之一行的内容搞混在一起(如果想了解其他选项,可以查看 --group--ungroup)。

注意:显然,这种方法在有多个CPU核心的机器上效果最好,因为默认情况下,GNU Parallel会在每个核心上运行一个任务。需要注意的是,与许多现代开发机器不同,便宜的AWS EC2和DigitalOcean的套餐通常只有一个虚拟CPU核心。因此,如果你想在一个核心上同时运行多个任务,就需要调整GNU Parallel的 --jobs 参数。例如,如果想在每个核心上运行两个爬虫,可以这样设置:

scrapy list | parallel --jobs 200% --line-buffer scrapy crawl
1

这段代码对我有效:

from scrapy import signals, log
from scrapy.xlib.pydispatch import dispatcher
from scrapy.conf import settings
from scrapy.http import Request
from multiprocessing.queues import Queue
from scrapy.crawler import CrawlerProcess
from multiprocessing import Process
# import your spider here
def handleSpiderIdle(spider):
        reactor.stop()
mySettings = {'LOG_ENABLED': True, 'ITEM_PIPELINES': '<name of your project>.pipelines.scrapermar11Pipeline'} 

settings.overrides.update(mySettings)

crawlerProcess = CrawlerProcess(settings)
crawlerProcess.install()
crawlerProcess.configure()

spider = <nameofyourspider>(domain="") # create a spider ourselves
crawlerProcess.crawl(spider) # add it to spiders pool

dispatcher.connect(handleSpiderIdle, signals.spider_idle) # use this if you need to handle idle event (restart spider?)

log.start() # depends on LOG_ENABLED
print "Starting crawler."
crawlerProcess.start()
print "Crawler stopped."

撰写回答