AWS LambdaでSeleniumを使ったときに詰まったところ


何をしようとしてたか

やろうとしてたことは、AWS Lambdaからseleniumを使ってtwitterのポストをCSV形式で取得するという感じで、具体的には以下のリポジトリをそのまま使おうとしてた。

ちなみに、Chromeのバージョン115以降には対応できていなかったので、いくつか依存パッケージのバージョンを上げるPRをした(なので、実際の処理で使ったのはフォークした自身のリポジトリの方)。

詰まったところ&解決策

ここからはやってる中で特に詰まったことのみ書いていく。

1. 非AWSベースイメージでのライタイムインターフェス

こちらのドキュメントに書いてあるのをよく見てなかったので数十分詰まった。ドキュメントを見たらちゃんと書いてあった。

Pythonを使用する場合には、pipで以下のパッケージをインストールし、Dockerfileのエントリーポイントとコマンドを適切に設定する必要がある。

pip install awslambdaric
# Dockerfile

...
ENTRYPOINT ["/usr/local/bin/python", "-m", "awslambdaric"]
CMD ["lambda_function.handler"]

ちなみに、このままだとローカルでテストできなくなってしまうので、その場合は以下の手順で検証用にローカルからLambdaと同様のエンドポイントを立ててあげることができる。

mkdir -p ~/.aws-lambda-rie && \
    curl -Lo ~/.aws-lambda-rie/aws-lambda-rie https://github.com/aws/aws-lambda-runtime-interface-emulator/releases/latest/download/aws-lambda-rie && \
    chmod +x ~/.aws-lambda-rie/aws-lambda-rie
docker run --platform linux/amd64 -d -v ~/.aws-lambda-rie:/aws-lambda -p 9000:8080 \
    --entrypoint /aws-lambda/aws-lambda-rie \
    docker-image:test \
        /usr/local/bin/python -m awslambdaric lambda_function.handler

2. ブラウザの実行ファイルが見つからない

これはLambda特有のものではなく、どちらかと言うと、コンテナ内でSeleniumを使う際の問題。調べればよく使われるベースイメージのものはたいてい出てくると思うが、python:3.12-slim-bullseyeでは以下のような構成でブラウザ(Firefox)の実行ファイルを認識させられた。

...
RUN apt-get update && \
    apt-get install -y --no-install-recommends \
    gcc \
    g++ \
    make \
    git \
    libffi-dev \
    firefox-esr \
    curl \
    gnupg && \
    rm -rf /var/lib/apt/lists/*
...

これらを入れてない場合はselenium側で「brower binary file not found(実行ファイルが見つからないよ)」みたいなエラーが出ていた。

3. webdriver-managerがドライバを実行時にインストールできない

ここがすごく詰まった。
Lambdaは実行環境をカスタムコンテナにする際、実行時に/tmp以外は書き込み権限がないようになっている。それを知らずに、webdriver-managerというpythonのパッケージでドライバを自動ダウンロードしようとしたら、「ドライバがないよ」って怒られてた。

そして、実はパッケージの以下の部分の実装によって、エラーが表示させる前に例外で終了してしまうようになっていたので、本来のエラーに気が付かなかった…本来は`self.__close_driver()`の前にロギングしなければならないはず。

# twitter-scraper-selenium/profile.py (L:126-129)

        except Exception as ex:
            self.__close_driver()
            logger.exception(
                "Error at method scrap : {} ".format(ex))

これに関しては解決策としては、webdriver-managerを使わずにDockerfile時点で決め打ちでドライバを入れてしまうか、webdriver-managerにドライバインストールの場所を変更できるようにする機能追加を入れるしかないと思う。(現時点では、webdriver-managerはパスの変更機能を持たず、カレントディレクトリかホームディレクトリにしか入れられない)

前者(ドライバを決め打ちで入れる)にしても、twitter-scraper-seleniumの方でwebdriver-managerを使う実装になってしまっている以上、そこを修正するか自前で実装するかになるのでかなり手間がかかってしまう。

そのため、今回はそもそもLambdaでseleniumを使わずに、適当に自宅でリソースの余ってるサーバ上で動かすことにした。(上記の問題は原因が分からずなんか気持ち悪かったので、時間を使って調査した)

この記事が気に入ったらサポートをしてみませんか?