如何将Scrapy依赖项打包为lambda?

时间:2019-07-19 00:46:38

标签: python aws-lambda scrapy

我正在编写一个依赖于Scrapy模块的python应用程序。它在本地工作正常,但是当我从aws lambda测试控制台运行它时失败了。我的python项目有一个requirements.txt文件,具有以下依赖性:

scrapy==1.6.0

我通过以下链接打包了所有依赖项:https://docs.aws.amazon.com/lambda/latest/dg/lambda-python-how-to-create-deployment-package.html。另外,我将源代码*.py放在zip文件的根目录下。我的打包脚本可以在https://github.com/zhaoyi0113/quote-datalake/blob/master/bin/deploy.sh中找到。

它基本上有两件事,首先运行命令pip install -r requirements.txt -t dist,将所有依赖项下载到dist目录。其次,将应用程序python源代码复制到dist目录中。

通过terraform完成部署,下面是配置文件。

provider "aws" {
  profile    = "default"
  region     = "ap-southeast-2"
}

variable "runtime" {
  default = "python3.6"
}

data "archive_file" "zipit" {
    type        = "zip"
    source_dir  = "crawler/dist"
    output_path = "crawler/dist/deploy.zip"
}
resource "aws_lambda_function" "test_lambda" {
  filename      = "crawler/dist/deploy.zip"
  function_name = "quote-crawler"
  role          = "arn:aws:iam::773592622512:role/LambdaRole"
  handler       = "handler.handler"
  source_code_hash = "${data.archive_file.zipit.output_base64sha256}"
  runtime = "${var.runtime}"
}

它压缩目录并将文件上传到lambda。

我发现当有一条语句Unable to import module 'handler': cannot import name 'etree'时,我在lambda import scrapy中遇到了运行时错误。我没有在代码中使用etree,所以我相信scrapy使用了某些东西。

我的源代码可以在https://github.com/zhaoyi0113/quote-datalake/tree/master/crawler上找到。只有两个简单的python文件。

如果我在本地运行它们,效果很好。该错误仅出现在lambda中。是否有将scrapy打包为lambda的其他方法?

2 个答案:

答案 0 :(得分:1)

您需要提供整个依赖关系树, scrapy 还具有一组依赖关系(它们也可能具有依赖关系)。

下载所有必需依赖项的最简单方法是使用pip

$ pip -t packages/ install scrapy

这会将 scrapy 及其所有依赖项下载到文件夹包中。

Scrapy具有lxmlpyOpenSSL作为依赖关系,其中包括已编译的组件。除非它们是静态编译的,否则可能会要求将所需的C库也安装在lambda VM上。

从lxml文档中需要:

  • libxml2版本2.9.2或更高版本。
  • libxslt 1.1.27版或更高版本。 我们建议使用libxslt 1.1.28或更高版本。

也许尝试将这些安装添加到您的部署脚本中。您应该可以使用(我正在猜测软件包名称)yum -y install libxml2 libxslt

另一个好主意是在Amazon Linux EC2实例上测试您的脚本,因为它与Lambda所执行的环境非常接近。

答案 1 :(得分:1)

基于与Tim的交流,此问题是由本地和lambda之间的库版本不兼容引起的。

解决此问题的最简单方法是使用docker image lambci/lambda通过以下命令构建软件包:

$ docker run -v $(pwd):/outputs -it --rm lambci/lambda:build-python3.6 pip install scrapy -t /outputs/