【问题标题】:Unable to get results from Scrapy on AWS Lambda无法从 AWS Lambda 上的 Scrapy 获取结果
【发布时间】:2018-09-12 09:35:19
【问题描述】:

我使用 python scrapy 库构建了一个爬虫。在本地运行时,它可以完美可靠地工作。我试图将它移植到 AWS lambda(我已经适当地打包了它)。但是,当我运行它时,进程在爬网运行时不会被阻止,而是在爬网程序返回没有结果之前完成。这些是我在它退出之前从日志中得到的最后几行:

2018-09-12 18:58:07 [scrapy.middleware] INFO: Enabled item pipelines:
[]
2018-09-12 18:58:07 [scrapy.core.engine] INFO: Spider opened

而通常我会获得有关被抓取页面的完整信息。我尝试在开始爬网后睡觉,安装钩针并添加其声明符并安装和使用this 特定框架,听起来它解决了这个问题,但它也不起作用。

我确定这是 Lambda 不尊重 scrapys 阻塞的问题,但我不知道如何解决它。

【问题讨论】:

  • 旁注:Lambda 可能不是 Scrapy 的理想选择,因为执行时间限制为 5 分钟。

标签: python python-3.x amazon-web-services scrapy aws-lambda


【解决方案1】:

我遇到了同样的问题,并通过为sqlite3 创建空模块来解决它,如以下答案所述:https://stackoverflow.com/a/44532317/5441099。显然,Scrapy 导入 sqlite3,但不一定使用它。 Python3 期望 sqlite3 在主机上,但 AWS Lambda 机器没有它。错误消息并不总是显示在日志中。

这意味着您可以通过切换到 Python2 或像我一样为 sqlite3 创建空模块来使其工作。

我的爬虫运行入口文件如下,在Lambda和Python3.6上运行:

# run_crawler.py
# crawl() is invoked from the handler function in Lambda
import os
from my_scraper.spiders.my_spider import MySpider
from scrapy.crawler import CrawlerProcess
# Start sqlite3 fix
import imp
import sys
sys.modules["sqlite"] = imp.new_module("sqlite")
sys.modules["sqlite3.dbapi2"] = imp.new_module("sqlite.dbapi2")
# End sqlite3 fix


def crawl():
    process = CrawlerProcess(dict(
        FEED_FORMAT='json',
        FEED_URI='s3://my-bucket/my_scraper_feed/' +
        '%(name)s-%(time)s.json',
        AWS_ACCESS_KEY_ID=os.getenv('AWS_ACCESS_KEY_ID'),
        AWS_SECRET_ACCESS_KEY=os.getenv('AWS_SECRET_ACCESS_KEY'),
    ))
    process.crawl(MySpider)
    process.start()  # the script will block here until all crawling jobs are finished


if __name__ == '__main__':
    crawl()

【讨论】:

  • 我真的很想对此进行测试,但遇到了一些不相关的问题。我最终构建了一个容器并使用了 Fargate。我相信这会解决它。
【解决方案2】:

正如@viktorAndersen 的回答解决了在 AWS Lambda 中刮擦崩溃/工作不正常的问题。

我有一个沉重的蜘蛛爬行 2000 个网址,我遇到了 2 个问题

  1. 当我运行 scrapy 函数超过 1 次时出现 ReactorNotRestartable 错误。第一次它工作正常,但从第二次调用我遇到了 ReactorNotRestartable。

  2. 当蜘蛛花费的时间超过预期的持续时间时,crochet.wait_for() 出现超时异常

这篇文章的灵感来自https://stackoverflow.com/a/57347964/12951298

    import sys
    import imp
    from scrapy.crawler import  CrawlerRunner
    from scrapy.utils.project import get_project_settings
    from scrapy.utils.log import configure_logging
    from twisted.internet import reactor;

    from crochet import setup, wait_for


    setup()

   sys.modules["sqlite"] = imp.new_module("sqlite")
   sys.modules["sqlite3.dbapi2"] = imp.new_module("sqlite.dbapi2")


   @wait_for(900)
   def crawl():

   '''
    wait_for(Timeout = inseconds)
   change the timeout accordingly
   this function will raise crochet.TimeoutError if more than 900
   seconds elapse without an answer being received
   '''
        spider_name="header_spider" #your spider name
        project_settings = get_project_settings()
        spider_loader = SpiderLoader(project_settings)

        spider_cls = spider_loader.load(spider_name)
        configure_logging()
        process = CrawlerRunner({**project_settings});
        d = process.crawl(spider_cls);
        return d;

   if __name__ == "__main__":
        main('', '')

【讨论】:

    猜你喜欢
    • 2018-01-26
    • 1970-01-01
    • 1970-01-01
    • 2020-01-30
    • 2020-06-14
    • 2022-12-29
    • 2021-09-04
    • 2019-11-01
    • 2018-08-12
    相关资源
    最近更新 更多