AWS LambdaでScrapyを動かす

pip install が必要なので、下記を使って動作確認とデプロイパッケージ作る方向で調査。

https://github.com/lambci/docker-lambda

この Docker イメージを使うと、AWS とほぼ同じような環境を Docker 上に再現して Lambda 関数を実行できる。また、レイヤー作成用に gcc などよく使うライブラリがインストールされた Docker イメージもセットで公開されており、EC2 上で開発する必要がなくなるので非常に便利!

まずはコンテナ内からボリューム割当したローカルディレクトリに pip install する。Python のバージョンは現在使っている 2.7 で。

docker run --rm -v "$PWD":/var/task lambci/lambda:build-python2.7 pip install -r requirements.txt -t python

とりあえず scrapy コマンドを呼ぶだけの lambda_function.py を作る。

import subprocess

def lambda_handler(event, context):
    subprocess.call(["scrapy", "crawl", "spider_name"])

その後、ライブラリをレイヤーとして使って実行。

docker run --rm -v "$PWD":/var/task:ro,delegated -v "$PWD"/python:/opt:ro,delegated lambci/lambda:python2.7 lambda_function.lambda_handler

するとコマンドが見つからないとのエラー。

[Errno 2] No such file or directory: OSError
Traceback (most recent call last):
File "/var/task/lambda_function.py", line 13, in lambda_handler
subprocess.call(["scrapy", "crawl", "spider_name"])

PATH に追加して呼び出せるようにした。

import subprocess

def lambda_handler(event, context):
    os.environ['PATH'] = os.environ['PATH'] + ":/opt/python/bin"
    subprocess.call(["scrapy", "crawl", "spider_name"])

今度はこのエラー。

Traceback (most recent call last):
File "/opt/python/bin/scrapy", line 5, in
from scrapy.cmdline import execute
ImportError: No module named scrapy.cmdline

コマンド実行ではなく CrawlerProcess を使えば OK。

from scrapy.crawler import CrawlerProcess
from scrapy.utils.project import get_project_settings

def lambda_handler(event, context):
    process = CrawlerProcess(get_project_settings())
    process.crawl('spider_name')
    process.start()

https://scrapy-ja.readthedocs.io/ja/latest/topics/practices.html#scrapy

デプロイパッケージ作成

レイヤー

zip -r scrapy.zip python

Lambda 関数

zip -r deploy.zip spider_name lambda_function.py scrapy.cfg
2022.11.14追記

いつの間にか Lambda がコンテナをサポートしていたらしく、lambci/docker-lambda は更新をやめた様子。Python 3.8 で止まっている。Lambda もだんだん Python のバージョンが上がって足切りされていくので、公式のコンテナ手順に移行した。

コメントを残す