无法从 AWS Lambda 上的 Scrapy 获取结果



我使用 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

而通常情况下,我会获得有关正在抓取的页面的全部信息。我尝试在开始爬行后睡觉,安装钩针并添加其声明符,并安装和使用这个听起来像是解决了这个问题但又不起作用的特定框架。

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

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

这意味着你可以通过切换到 Python2 来让它工作,或者像我一样为sqlite3创建空模块。

我运行爬虫的入口文件如下,它适用于带有 Python3.6 的 Lambda:

# 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()

正如 @viktorAndersen 的答案解决了在 AWS Lambda 中无法按预期崩溃/工作的问题。

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

  1. 反应器不可重新启动错误,当我运行刮擦功能超过 1 次。第一次它工作正常,但从第二次调用开始,我遇到了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('', '')

最新更新