Scrapy:运行 CrawlProcess() 时出现twisted.internet.error.ReactorNotRestartable

问题描述 投票:0回答:4

我正在尝试从脚本运行我的 scrapy 。 我正在使用 CrawlerProcess,并且只有一个蜘蛛可以运行。

我已经被这个错误困扰了一段时间了,我已经尝试了很多方法来更改设置,但每次运行蜘蛛时,我都会得到

twisted.internet.error.ReactorNotRestartable

我一直在寻找解决此错误的方法,并且我相信只有当您尝试多次调用 process.start() 时才会出现此错误。但我没有。

这是我的代码:

import scrapy
from scrapy.utils.log import configure_logging

from scrapyprefect.items import ScrapyprefectItem
from scrapy.crawler import CrawlerProcess
from scrapy.utils.project import get_project_settings


class SpiderSpider(scrapy.Spider):
    name = 'spider'
    start_urls = ['http://www.nigeria-law.org/A.A.%20Macaulay%20v.%20NAL%20Merchant%20Bank%20Ltd..htm']

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    def parse(self, response):
        item = ScrapyprefectItem()
        ...

        yield item


process = CrawlerProcess(settings=get_project_settings())
process.crawl('spider')
process.start()

错误:

Traceback (most recent call last):
  File "/Users/pluggle/Documents/Upwork/scrapyprefect/scrapyprefect/spiders/spider.py", line 59, in <module>
    process.start()
  File "/Users/pluggle/Documents/Upwork/scrapyprefect/venv/lib/python3.7/site-packages/scrapy/crawler.py", line 309, in start
    reactor.run(installSignalHandlers=False)  # blocking call
  File "/Users/pluggle/Documents/Upwork/scrapyprefect/venv/lib/python3.7/site-packages/twisted/internet/base.py", line 1282, in run
    self.startRunning(installSignalHandlers=installSignalHandlers)
  File "/Users/pluggle/Documents/Upwork/scrapyprefect/venv/lib/python3.7/site-packages/twisted/internet/base.py", line 1262, in startRunning
    ReactorBase.startRunning(self)
  File "/Users/pluggle/Documents/Upwork/scrapyprefect/venv/lib/python3.7/site-packages/twisted/internet/base.py", line 765, in startRunning
    raise error.ReactorNotRestartable()
twisted.internet.error.ReactorNotRestartable

我注意到这只在我尝试将项目保存到 mongodb 时才会发生。 管道.py:

import logging
import pymongo


class ScrapyprefectPipeline(object):
    collection_name = 'SupremeCourt'

    def __init__(self, mongo_uri, mongo_db):
        self.mongo_uri = mongo_uri
        self.mongo_db = mongo_db

    @classmethod
    def from_crawler(cls, crawler):
        # pull in information from settings.py
        return cls(
            mongo_uri=crawler.settings.get('MONGO_URI'),
            mongo_db=crawler.settings.get('MONGO_DATABASE')
        )

    def open_spider(self, spider):
        # initializing spider
        # opening db connection
        self.client = pymongo.MongoClient(self.mongo_uri)
        self.db = self.client[self.mongo_db]

    def close_spider(self, spider):
        # clean up when spider is closed
        self.client.close()

    def process_item(self, item, spider):
        # how to handle each post
        self.db[self.collection_name].insert(dict(item))
        logging.debug("Post added to MongoDB")
        return item

如果我将 pipeline.py 更改为默认值,即...

import logging
import pymongo

class ScrapyprefectPipeline(object):
    def process_item(self, item, spider):
        return item

...脚本运行良好。 我认为这与我如何设置 pycharm 设置来运行代码有关。 因此,作为参考,我还包括我的 pycharm 设置

我希望有人能帮助我。如果需要更多细节请告诉我

python scrapy pycharm twisted
4个回答
4
投票

雷纳尔多,

非常感谢 - 你保存了我的项目!

你让我想到了这个想法,可能会发生这种情况,因为如果脚本在与蜘蛛定义相同的文件中启动该进程,则可能会发生这种情况。因此,每次 scrapy 导入蜘蛛定义时都会执行它。我不是 scrapy 方面的专家,但可能它在内部执行了几次,因此我们遇到了这个错误问题。

你的建议显然解决了问题!

另一种方法可能是将蜘蛛类定义和运行它的脚本分开。可能,这就是 scrapy 所采用的方法,这就是为什么在它的 Running Spider from script 文档中,它甚至没有提到这个

__name__
检查。

所以我所做的如下:

  • 在项目根目录中,我有 sites 文件夹,其中有 site_spec.py 文件。这只是一个包含一些目标站点特定信息(URL 结构等)的实用程序文件。我在这里提到它只是为了向您展示如何将各种实用程序模块导入到蜘蛛类定义中;

  • 在项目根目录中,我有 spiders 文件夹和 my_spider.py 类定义。在该文件中,我导入带有指令的 site_spec.py 文件:

from sites import site_spec

值得一提的是,运行蜘蛛的脚本(您提供的脚本)已从类定义 my_spider.py 文件中删除。另请注意,我导入了 site_spec.py 文件,其路径与 run.py 文件相关(见下文),但与类定义文件无关,其中该指令按照预期发出(python我猜是相对进口)

  • 最后,在项目根目录中,我有 run.py 文件,从脚本运行 scrapy:
from scrapy.crawler import CrawlerProcess
from spiders.my_spider  import MySpider # this is our friend in subfolder **spiders**
from scrapy.utils.project import get_project_settings

# Run that thing!

process = CrawlerProcess(get_project_settings())
process.crawl(MySpider)
process.start() # the script will block here until the crawling is finished

通过这个设置,我终于能够摆脱这个twisted.internet.error.ReactorNotRestartable

非常感谢!!!


3
投票

好的。我解决了。 所以我认为,在管道中,当scraper进入open_spider时,它会再次运行spider.py,并第二次调用process.start()。

为了解决这个问题,我在蜘蛛中添加了这个,这样 process.start() 只会在你运行蜘蛛时执行:

if __name__ == '__main__':
    process = CrawlerProcess(settings=get_project_settings())
    process.crawl('spider')
    process.start()

0
投票

尝试更换Scrapy和Twisted版本。这不是解决方案,但有效。

pip 安装 Twisted==22.1.0 pip 安装 Scrapy==2.5.1


0
投票

就我而言,问题是我试图运行 每次添加蜘蛛时的

start()
方法:

这不起作用:

对于 scrappers_names 中的名称: process.crawl(名称)

© www.soinside.com 2019 - 2024. All rights reserved.