AWS Lambda PythonでSeleniumを使える環境を構築する

2022.12.26

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

データアナリティクス事業本部のueharaです。

今回はAWS Lambda (Python)で、WebアプリケーションをテストするためのポータブルフレームワークであるSeleniumを使える環境を構築してみたいと思います。

バケットの準備

今回はLambda Layerを構築することになりますが、その資材をS3に配置するため、まずバケットを用意します。

AWSコンソールでサービスからS3を検索します。

「バケットを作成」から作業用のバケット「selenium-work」という名前のバケットを作成します。

その他の設定はデフォルトのままとします。

パッケージの用意

まず、Lambda (Python)でSeleniumを利用できるようにするために、各パッケージの用意を行います。 パッケージの用意には、無料で使えるサービスであるAWS CloudShellを利用します。

Seleniumのダウンロード

まず、東京リージョンを選択します。

次に、サービス欄からCloudShellを検索して、起動します。

起動ができたら、Pythonのデフォルトバージョンを確認してみます。

python --version

デフォルトではPython 2.7となっているようです。

デフォルトがPython 2.7だったので、今度は明示的にPython 3を指定してバージョンを確認してみます。

python3 --version

Python 3の場合、バージョンはPython 3.7となっていました。

今回はこのPython 3.7を利用したいと思います。

CloudShell上でpipを利用して、 ./python/lib/python3.7/site-packages 配下にSeleniumをダウンロードします。

pip3 install selenium==3.141.0 -t ./python/lib/python3.7/site-packages --use-feature=2020-resolver

※pipを利用した際に、boto3 1.26.11 requires botocore=1.29.11というエラーが発生する可能性がありますが、今回のSeleniumのダウンロードに影響は無いので無視しても大丈夫です。

ダウンロードが完了すると、直下に python ディレクトリができていると思うので、後でローカル環境にDLできるようにzip化しておきます。

zip -r python python

この時点でlsコマンドを利用すると、ディレクトリは以下のようになっていると思います。

chromedriver, headless-chromiumのダウンロード

次に、chromedriver, headless-chromiumを用意します。

まずは、CloudShell上で保存用ディレクトリを作成します。

mkdir headless

作成したディレクトリに移動します。

cd headless

次に、headless-chromiumのダウンロードを行います。

curl -SL https://github.com/adieuadieu/serverless-chrome/releases/download/v1.0.0-55/stable-headless-chromium-amazonlinux-2017-03.zip > headless-chromium.zip

ダウンロードが完了したら、展開します。

unzip -o headless-chromium.zip -d .

zipファイルの方はもう使わないので削除します。

rm headless-chromium.zip

続いて、chromedriverをダウンロードします。 先程ダウンロードしたheadless-chromiumのchromeバージョンは69なので、chromedriverのバージョンは2.43を利用します。

curl -SL https://chromedriver.storage.googleapis.com/2.43/chromedriver_linux64.zip > chromedriver.zip

先程と同じように、展開してzipファイルの方は削除を行います。

unzip -o chromedriver.zip -d .
rm chromedriver.zip

ここまでの作業が完了したら、homeディレクトリに戻り、headlessディレクトリをzip化します。

cd
zip -r headless headless

この時点で再度lsコマンドを利用すると、ディレクトリは以下のようになっていると思います。

用意したパッケージのS3へコピー

先の手順でzip化したファイル(python.zip, headless.zip)を、CloudShellからS3へコピーを行います。

CloudShell上ではAWS CLIのコマンドが使えますので、以下のコマンドでコピーを行います。

aws s3 cp python.zip s3://selenium-work

次のように表示されていればコピーは成功です。

同様に、headless.zipの方もS3へコピーを行います。

aws s3 cp headless.zip s3://selenium-work

Lambda Layersの構築

AWSコンソール上からAWS Lambdaのサービスに移動して、「レイヤー」を選択します。

seleniumレイヤーの作成

以下の設定で、seleniumレイヤーを作成します。

名前:selenium-layer
「Amazon S3 からファイルをアップロードする」を選択し、先の作業でS3へアップロードしたpython.zipのパス(s3://selenium-work/python.zip)を指定
ランタイム:Python3.7

headlessレイヤーの作成

以下の設定で、headlessレイヤーを作成します。

名前:headless-layer
「Amazon S3 からファイルをアップロードする」を選択し、先の作業でS3へアップロードしたheadless.zipのパス(s3://selenium-work/headless.zip)を指定
ランタイム:Python3.7

実行テスト

Lambda Layersの構築が完了したら、早速実行テストを行います。

関数の作成

AWS Lambdaのサービスから「関数の作成」を行います。

関数名はご自身のお好きな名前をつけ、ランタイムはPython 3.7を指定します。

関数名:uehara-test-func
ランタイム:Python 3.7

レイヤーの追加・設定変更

関数の作成が完了したら、下の方にある「レイヤー」から「レイヤーの追加」を行います。

カスタムレイヤーにチェックを入れ、「selenium-layer」を選択します。

selenium-layerの追加が完了したら、同様に、「headless-layer」の追加も行います。

以下のように、2つのレイヤーが追加されていれば成功です。

次に、「設定」の「一般設定」から、メモリサイズとタイムアウトをよしなに変更します。
※デフォルトのメモリ128MBとタイムアウト3秒では、Seleniumを動かすのが難しいため。

私の場合はメモリを256MBにして、タイムアウトを1分にしました。

コードの作成・デプロイ

ここまで作成ができたら、コードを作成しデプロイを行います。

作成したコードは以下の通りです。

from selenium import webdriver

def lambda_handler(event, context):
    URL = "https://dev.classmethod.jp/"

    options = webdriver.ChromeOptions()
    # headless-chromiumのパスを指定
    options.binary_location = "/opt/headless/headless-chromium"
    options.add_argument("--headless")
    options.add_argument('--single-process')
    options.add_argument('--disable-dev-shm-usage')
    options.add_argument("--no-sandbox")

    browser = webdriver.Chrome(
        # chromedriverのパスを指定
        executable_path="/opt/headless/chromedriver",
        options=options
    )

    browser.get(URL)
    title = browser.title
    browser.close()
    return title

作成したレイヤーは、Lambdaの実行環境の /opt ディレクトリに展開されるので、headless-chroniumやchromedriverのパスはそれぞれ/opt/headless/headless-chromium/opt/headless/chromedriverのように設定します。

PythonのライブラリをLayerにする場合は /opt/python または /opt/python/lib/python3.7/site-packages に展開されるように作ると自然にimportできるようになるので、importに関しては特別な操作は必要ありません。
※今回は後者で展開されるようにディレクトリを作成しているため

コンソール上でコードを入力し、「Deploy」ボタンを押すとデプロイを行うことができます。

テスト実行

テスト実行するために、「Test」ボタンからテストイベントを作成します。

今回のテスト実行にイベントJSONは本質的な意味を持たないので、テンプレートは「hello-world」のまま「MyTestEvent」という名前をつけてそのまま保存を行います。

保存が完了したら、「Test」ボタンを押してテストを行います。

実行後、次のようにDevelopersIOのタイトルが取得できていれば成功です。

最後に

今回はAWS Lambda PythonでSeleniumを使える環境を構築し、実行テストまで行い動作の確認を行ってみました。

LambdaでSeleniumを利用したいという方の参考になりましたら幸いです。

参考文献