4
4

Playwright PythonをAWS Lambdaで動かす

Posted at

たまにPlaywrightをLambdaで動かしたくなりますよね。

すでにいろいろな方が挑戦されているようで、簡単に使えるLambdaレイヤーが公開されているようです。

ただ、そういうことじゃないんです。自分でやることに意味があるんです。なんとか動作しましたので、ご紹介。

きっかけ

先日投稿したこちらの記事で、LangChainの「AsyncChromiumLoader」を紹介しました。

これをLambda化したいなぁと思ったのがきっかけです。(そしてBedrock Agentsから呼び出したい)

AsyncChromiumLoaderは内部でPlaywrightが使われているのですが、先ほど解説した「chromium.launch」の呼び出し部分のargsを外部から指定する方法がなかったので、素のPlaywrightを使って検証しました。

Lambda化ができたので、あとはBedrock Agentsのアクショングループとして登録してやれば、Web検索ができるエージェントが作成できる!

はずでした。。。

Bedrock Agentsのクオータ制限で、「Lambda レスポンスペイロードサイズは25KBまで」というものがあり、この制限に引っかかってしまうサイトが多く、実用には至りませんでした。

Playwrightを動作させる条件を確認

システム要件

  • Python 3.8 or higher.
  • Windows 10+, Windows Server 2016+ or Windows Subsystem for Linux (WSL).
    macOS 13 Ventura, or macOS 14 Sonoma.
  • Debian 11, Debian 12, Ubuntu 20.04 or Ubuntu 22.04, Ubuntu 24.04, on x86-64 and arm64 architecture.

インストール手順

Playwrightのインストールはpip install playwrightだけではなく、ブラウザのダウンロードなどの手順が必要です。

Shell
pip install playwright
playwright install --with-deps chromium

--with-depsはシステムの依存ライブラリをあわせて行うオプションです

Lambdaで同様のことを行う必要があるため、zip形式ではなくコンテナイメージ形式で作成します。

Dockerfileを作成

AWSが提供するベースイメージ(public.ecr.aws/lambda/python:3.12)はOSがAmazon Linux 2023のため、Playwrightのシステム要件に合致しません。そのため、インストール手順を実行してもエラーになってしまいます。

BEWARE: your OS is not officially supported by Playwright; installing dependencies for ubuntu20.04-x64 as a fallback.
Installing dependencies...
sh: line 1: apt-get: command not found
Failed to install browsers
Error: Installation process exited with code: 127

ランタイムインターフェイスクライアントで代替ベースイメージを使用する」を参考に、AWS提供ではないベースイメージを使用する方法を採用します。

参考サイトを少しカスタマイズし、以下のようなDockerファイルを作成します。

ベースイメージはpython:3.12-slimです。

Dockerfile
# Define custom function directory
ARG FUNCTION_DIR="/function"

# Use a slim version of the base Python image to reduce the final image size
FROM python:3.12-slim

# Include global arg in this stage of the build
ARG FUNCTION_DIR

ENV PLAYWRIGHT_BROWSERS_PATH=/playwright

# Copy function code
RUN mkdir -p ${FUNCTION_DIR}
COPY requirements.txt ${FUNCTION_DIR}

# Set working directory to function root directory
WORKDIR ${FUNCTION_DIR}

# Install the function's dependencies
RUN pip install -r requirements.txt && \
    playwright install --with-deps chromium

COPY app.py ${FUNCTION_DIR}

# Set runtime interface client as default command for the container runtime
ENTRYPOINT [ "/usr/local/bin/python", "-m", "awslambdaric" ]
# Pass the name of the function handler as an argument to the runtime
CMD [ "app.lambda_handler" ]

「PLAYWRIGHT_BROWSERS_PATH」を指定しない場合、chromiumが「/root/.cache/ms-playwright」配下にダウンロードされます。Lambdaの実行ユーザーはrootではないため、「PLAYWRIGHT_BROWSERS_PATH」を明示的に指定します。

PLAYWRIGHT_BROWSERS_PATHは、Lambdaの環境変数にもセットする必要があります。

template.yaml
Resources:
  PlaywrightFunction:
    Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
    Properties:
      PackageType: Image
      Architectures:
        - x86_64
      Environment:
        Variables:
          PLAYWRIGHT_BROWSERS_PATH: /playwright     # これ!
    Metadata:
      Dockerfile: Dockerfile
      DockerContext: ./hello_world
      DockerTag: python3.12-v1

その他のコードを作成

requirements.txtを作成します。

requirements.txt
awslambdaric
playwright

awslambdaricは、「AWS Lambda Python Runtime Interface Client」です。これをインストールすると、AWS提供ではないベースイメージでも簡単にLambdaで動作させることができます。

最後にPythonコードを作成します。

app.py
from playwright.sync_api import sync_playwright

with sync_playwright() as p:

    browser = p.chromium.launch(
        args=[
            "--single-process",
            "--no-zygote",
            "--no-sandbox",
            "--disable-gpu",
            "--disable-dev-shm-usage",
            "--headless=new",
        ]
    )

    context = browser.new_context(user_agent=user_agent)
    page = context.new_page()

    response = page.goto(url=url)

    content = page.content()
    title = page.title()

    browser.close()

argsオプションを指定します。

オプション 説明
--single-process Runs the renderer and plugins in the same process as the browser
--no-zygote Disables the use of a zygote process for forking child processes. Instead, child processes will be forked and exec'd directly. Note that --no-sandbox should also be used together with this flag because the sandbox needs the zygote to work.
--no-sandbox Disables the sandbox for all process types that are normally sandboxed. Meant to be used as a browser-level switch for testing purposes only.
--disable-gpu Disables GPU hardware acceleration. If software renderer is not in place, then the GPU process won't launch.
--disable-dev-shm-usage The /dev/shm partition is too small in certain VM environments, causing Chrome to fail or crash (see http://crbug.com/715363). Use this flag to work-around this issue (a temporary directory will always be used to create anonymous shared memory files).
--headless=new Run in headless mode, i.e., without a UI or display server dependencies.

それぞれの意味はよくわかりませんが、以下を参考に設定したところうまく動作しました。
引用元:https://peter.sh/experiments/chromium-command-line-switches/

これでうまくいくと思います。

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4