Scrapy 在 AWS Lambda 上运行时抛出错误 ReactorNotRestartable
Scrapy throws error ReactorNotRestartable when runnning on AWS Lambda
我已经部署了一个 scrapy 项目,它会在 lambda api 请求到来时进行抓取。
它在第一次 api 调用时运行完美,但后来失败并抛出 ReactorNotRestartable 错误。
据我所知,AWS Lambda 生态系统并未终止进程,因此反应器仍存在于内存中。
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()
我有一个解决方法,就是在启动函数中插入一个标志来不停止反应器
process.start(stop_after_crawl=False)
但问题是我不得不等到 lambda 调用超时。
尝试了其他解决方案,但 none 似乎 work.Can 有人指导我如何解决这个问题。
您可以尝试使用 https://pypi.python.org/pypi/crochet 协调非主线程中来自 Lambda 控制的主线程的反应器 运行 的使用。
Crochet 将为您进行线程反应器初始化,并提供工具使从主反应器线程中调用代码变得容易(并获得结果)。
这可能更符合 Lambda 对您的代码的期望。
此问题并非 AWS Lambda 独有 - 请参阅 running a spider in a Celery task。
您可以尝试 ScrapyScript(披露:我写的)。它生成一个子进程来支持 Twisted 反应器,阻塞直到所有提供的蜘蛛都完成,然后退出。它是用 Celery 编写的,但用例相似。
在你的情况下,这应该有效:
from scrapyscript import Job, Processor
def run_company_details_scrapy(event, context):
job = Job(CompanyDetailsSpidySpider())
Processor().run(job)`
最近遇到同样的问题,Crochet因为各种原因不想工作
最终我们采用了肮脏的解决方案:最后调用 sys.exit(0)
(如果发现错误则调用 sys.exit(1)
,而不是任何查看 return 代码 AFAICT) lambda 处理函数。这非常有效。
如果你打算从你的 Lambda return 一个 响应 显然不好,但如果你使用 Scrapy,数据可能已经通过你的管道,使用调度程序作为您的 Lambda 的触发器,因此无需响应。
注意:您将在 CloudWatch 中收到来自 AWS 的通知:
RequestId: xxxx Process exited before completing request
我在 AWS lambda 上遇到错误 ReactorNotRestartable
,然后我找到了这个解决方案
默认情况下,scrapy
的异步特性不能很好地与 Cloud Functions 配合使用,因为我们需要一种方法来阻止抓取,以防止函数提前返回和实例正在运行在进程终止之前被杀死。
相反,我们可以使用 scrapydo
以阻塞方式 运行 您现有的蜘蛛:
<div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
<div class="snippet-code">
<pre><code>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)
我已经部署了一个 scrapy 项目,它会在 lambda api 请求到来时进行抓取。
它在第一次 api 调用时运行完美,但后来失败并抛出 ReactorNotRestartable 错误。
据我所知,AWS Lambda 生态系统并未终止进程,因此反应器仍存在于内存中。
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()
我有一个解决方法,就是在启动函数中插入一个标志来不停止反应器
process.start(stop_after_crawl=False)
但问题是我不得不等到 lambda 调用超时。
尝试了其他解决方案,但 none 似乎 work.Can 有人指导我如何解决这个问题。
您可以尝试使用 https://pypi.python.org/pypi/crochet 协调非主线程中来自 Lambda 控制的主线程的反应器 运行 的使用。
Crochet 将为您进行线程反应器初始化,并提供工具使从主反应器线程中调用代码变得容易(并获得结果)。
这可能更符合 Lambda 对您的代码的期望。
此问题并非 AWS Lambda 独有 - 请参阅 running a spider in a Celery task。
您可以尝试 ScrapyScript(披露:我写的)。它生成一个子进程来支持 Twisted 反应器,阻塞直到所有提供的蜘蛛都完成,然后退出。它是用 Celery 编写的,但用例相似。
在你的情况下,这应该有效:
from scrapyscript import Job, Processor
def run_company_details_scrapy(event, context):
job = Job(CompanyDetailsSpidySpider())
Processor().run(job)`
最近遇到同样的问题,Crochet因为各种原因不想工作
最终我们采用了肮脏的解决方案:最后调用 sys.exit(0)
(如果发现错误则调用 sys.exit(1)
,而不是任何查看 return 代码 AFAICT) lambda 处理函数。这非常有效。
如果你打算从你的 Lambda return 一个 响应 显然不好,但如果你使用 Scrapy,数据可能已经通过你的管道,使用调度程序作为您的 Lambda 的触发器,因此无需响应。
注意:您将在 CloudWatch 中收到来自 AWS 的通知:
RequestId: xxxx Process exited before completing request
我在 AWS lambda 上遇到错误 ReactorNotRestartable
,然后我找到了这个解决方案
默认情况下,scrapy
的异步特性不能很好地与 Cloud Functions 配合使用,因为我们需要一种方法来阻止抓取,以防止函数提前返回和实例正在运行在进程终止之前被杀死。
相反,我们可以使用 scrapydo
以阻塞方式 运行 您现有的蜘蛛:
<div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
<div class="snippet-code">
<pre><code>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)