首页 > 解决方案 > 使用 Google Cloud Functions 时带有 scrapy 的 ReactorNotRestartable

问题描述

我正在尝试使用 Google Cloud Functions 发送多个抓取请求。但是,我似乎得到了ReactorNotRestartable错误。从 StackOverflow 上的其他帖子,例如这个,我了解到这是因为无法重新启动反应器,特别是在执行循环时。

解决这个问题的方法是将start()外部放在 for 循环中。但是,对于 Cloud Functions,这是不可能的,因为每个请求在技术上都应该是独立的。

是否CrawlerProcess使用 Cloud Functions 以某种方式缓存?如果是这样,我们如何才能消除这种行为。

例如,我尝试将导入和初始化过程放在一个函数内部,而不是外部,以防止导入缓存,但这不起作用:

# main.py

def run_single_crawl(data, context):
    from scrapy.crawler import CrawlerProcess
    process = CrawlerProcess()

    process.crawl(MySpider)
    process.start()

标签: pythongoogle-cloud-platformscrapygoogle-cloud-functions

解决方案


默认情况下,scrapyCloud Functions 的异步特性不能很好地工作,因为我们需要一种阻止爬取的方法,以防止函数提前返回并在进程终止之前终止实例。

相反,我们可以使用scrapydo以阻塞方式运行您现有的蜘蛛:

requirements.txt

scrapydo

main.py

import scrapy
import scrapydo

scrapydo.setup()


class MyItem(scrapy.Item):
    url = scrapy.Field()


class MySpider(scrapy.Spider):
    name = "example.com"
    allowed_domains = ["example.com"]
    start_urls = ["http://example.com/"]

    def parse(self, response):
        yield MyItem(url=response.url)


def run_single_crawl(data, context):
    results = scrapydo.run_spider(MySpider)

这也显示了一个简单的示例,说明如何scrapy.Item从蜘蛛获取一个或多个并从爬虫中收集结果,如果不使用scrapydo.

另外:确保您为您的项目启用了计费。默认情况下,Cloud Functions 无法发出出站请求,爬虫会成功,但不会返回任何结果。


推荐阅读