在AWS Lambda上运行时,Scrapy抛出错误ReactorNotRestartable

svmlkihl  于 2022-11-09  发布在  React
关注(0)|答案(4)|浏览(209)

我已经部署了一个Scrapy项目,每当lambda api请求到来时,它就会爬网。
它在第一次API调用时运行良好,但后来失败并抛出ReactorNotRestartable错误。
据我所知,AWS Lambda生态系统没有杀死进程,因此reactor仍然存在于内存中。
lambda日志错误如下:

Traceback (most recent call last):
File "/var/task/aws-lambda.py", line 42, in run_company_details_scrapy
process.start()
File "./lib/scrapy/crawler.py", line 280, in start
reactor.run(installSignalHandlers=False)  # blocking call
File "./lib/twisted/internet/base.py", line 1242, in run
self.startRunning(installSignalHandlers=installSignalHandlers)
File "./lib/twisted/internet/base.py", line 1222, in startRunning
ReactorBase.startRunning(self)
File "./lib/twisted/internet/base.py", line 730, in startRunning
raise error.ReactorNotRestartable()
ReactorNotRestartable

lambda处理函数为:

def run_company_details_scrapy(event, context):
   process = CrawlerProcess()
   process.crawl(CompanyDetailsSpidySpider)
   process.start()

我有一个变通办法,通过在start函数中插入一个标志,不停止reactor

process.start(stop_after_crawl=False)

但这样做的问题是,我必须等到lambda调用超时。
尝试了其他的解决方案,但似乎都不起作用。有人能指导我如何解决这个问题吗?

pgky5nke

pgky5nke1#

最近也有同样的问题,钩针不想工作的各种原因。
最后,我们采用了肮脏的解决方案:只需在lambda处理函数的末尾调用sys.exit(0)(或者sys.exit(1),如果捕捉到错误,并不意味着返回代码AFAICT)。
如果您打算从Lambda返回一个 response,这显然不太好,但是如果您使用Scrapy,数据可能已经通过您的管道持久化了,使用调度程序作为Lambda的触发器,因此不需要响应。
注意:您 * 将 * 在CloudWatch中收到AWS的通知:

RequestId: xxxx Process exited before completing request
hlswsv35

hlswsv352#

这个问题并不是AWS Lambda独有的-请参阅running a spider in a Celery task
您可以尝试ScrapyScript(披露:它生成一个子进程来支持Twisted reactor,阻塞直到所有提供的spider都完成,然后退出。它是考虑到Celery而编写的,但是用例是相似的。
在您的情况下,这应该是可行的:

from scrapyscript import Job, Processor
def run_company_details_scrapy(event, context):
    job = Job(CompanyDetailsSpidySpider())
    Processor().run(job)`
r7xajy2e

r7xajy2e3#

我在AWS lambda上遇到了错误ReactorNotRestartable,在我找到这个解决方案之后
默认情况下,scrapy的异步特性不会很好地与云函数一起工作,因为我们需要一种方法来阻止爬行,以防止函数提前返回,并防止在进程终止前杀死示例。
相反,我们可以使用scrapydo以阻塞方式运行现有的spider:

import scrapy
import scrapy.crawler as crawler
rom scrapy.spiders import CrawlSpider
import scrapydo

scrapydo.setup()

# your spider

class QuotesSpider(scrapy.Spider):
    name = "quotes"
    start_urls = ['http://quotes.toscrape.com/tag/humor/']

    def parse(self, response):
        for quote in response.css('div.quote'):
            print(quote.css('span.text::text').extract_first())

scrapydo.run_spider(QuotesSpider)
e1xvtsh3

e1xvtsh34#

您可以尝试使用https://pypi.python.org/pypi/crochet来协调在Lambda控制的主线程的非主线程中运行的React器的使用。
Crochet将为您完成线程化React器的初始化,并提供工具,使您可以轻松地从main调用React器线程中的代码(并获得结果)。
这可能更符合Lambda对您的代码的期望。

相关问题