ReactorNotRestartable - 扭曲和scrapy

时间:2017-06-27 19:09:13

标签: django web-applications scrapy twisted reactor

在您将我与其他相关答案联系起来之前,请注意我已阅读过它们,但仍然有点困惑。好的,我们走了。

所以我在Django中创建了一个webapp。我正在导入最新的scrapy库来抓取一个网站。我没有使用芹菜(我对它知之甚少,但在与此相关的其他主题中看到了它。)

我们网站的其中一个网址/ crawl /旨在启动抓取工具的运行。它是我们网站中唯一需要使用scrapy的网址。以下是访问URL时调用的函数:

def crawl(request):
  configure_logging({'LOG_FORMAT': '%(levelname)s: %(message)s'})
  runner = CrawlerRunner()

  d = runner.crawl(ReviewSpider)
  d.addBoth(lambda _: reactor.stop())
  reactor.run() # the script will block here until the crawling is finished

  return render(request, 'index.html')

您会注意到这是对其网站上的scrapy教程的改编。当服务器开始运行时第一次访问此URL时,一切都按预期工作。第二次,进一步抛出ReactorNotRestartable异常。我知道当一个已经停止的反应堆被发出再次启动的命令时会发生这种异常,这是不可能的。

查看示例代码,我会假设行" runner = CrawlerRunner()"每次访问此URL时,都会返回一个~new_ reactor。但我相信也许我对扭曲反应堆的理解还不完全清楚。

每次访问此网址时,如何获取并运行新反应堆?

非常感谢

1 个答案:

答案 0 :(得分:1)

一般来说,你不能有一个新的反应堆。有一个全球性的。这显然是一个错误,也许将来会得到纠正,但那是当前的事态。

您可以使用Crochet来管理单个反应堆运行(在整个过程的生命周期内 - 不会重复启动和停止)在单独的线程中。

考虑the example from the Crochet docs

#!/usr/bin/python
"""
Do a DNS lookup using Twisted's APIs.
"""
from __future__ import print_function

# The Twisted code we'll be using:
from twisted.names import client

from crochet import setup, wait_for
setup()


# Crochet layer, wrapping Twisted's DNS library in a blocking call.
@wait_for(timeout=5.0)
def gethostbyname(name):
    """Lookup the IP of a given hostname.

    Unlike socket.gethostbyname() which can take an arbitrary amount of time
    to finish, this function will raise crochet.TimeoutError if more than 5
    seconds elapse without an answer being received.
    """
    d = client.lookupAddress(name)
    d.addCallback(lambda result: result[0][0].payload.dottedQuad())
    return d


if __name__ == '__main__':
    # Application code using the public API - notice it works in a normal
    # blocking manner, with no event loop visible:
    import sys
    name = sys.argv[1]
    ip = gethostbyname(name)
    print(name, "->", ip)

这为您提供了使用Twisted API实现的阻止gethostbyname功能。该实现使用twisted.names.client,它只依赖于能够导入全局反应堆。

请注意,没有reactor.runreactor.stop来电 - 只是Crochet setup来电。