概要
aws lambdaでPlaywrightを動作させた。
ローカルで動作させる場合と異なり、Lambdaにはブラウザがない。
ヘッドレスブラウザを含んだLayerを利用することにした。
ソース
cdk/lib/playwright-stack.ts
import { Aspects, Duration, Stack, StackProps, Tag } from 'aws-cdk-lib';
import { LayerVersion, Runtime } from 'aws-cdk-lib/aws-lambda';
import { NodejsFunction } from 'aws-cdk-lib/aws-lambda-nodejs';
import { Construct } from 'constructs';
export class PlayWrightStack extends Stack {
constructor(scope: Construct, id: string, props: StackProps) {
super(scope, id, props);
new NodejsFunction(this, 'playWrightLambda', {
runtime: Runtime.NODEJS_18_X,
memorySize: 1024,
timeout: Duration.seconds(10),
entry: `../src/handler/invoke/playwright.ts`,
bundling: { externalModules: ['@sparticuz/chromium'] },
layers: [
LayerVersion.fromLayerVersionArn(
this,
'chromium-lambda-layer',
'arn:aws:lambda:ap-northeast-1:764866452798:layer:chrome-aws-lambda:39',
),
],
});
Aspects.of(this).add(new Tag('Stack', 'PlayWrightStack'));
}
}
packege.json
{
"name": "aws-cdk-v2",
"dependencies": {
"playwright-core": "^1.39.0"
},
"devDependencies": {
"@sparticuz/chromium": "^118.0.0",
"@types/aws-lambda": "^8.10.126",
"typescript": "^5.2.2"
}
}
src/handler/invoke/playwright.ts
import { Handler } from 'aws-lambda';
import { chromium } from 'playwright-core';
const sparticuzChromium = require('@sparticuz/chromium');
sparticuzChromium.setHeadlessMode = true;
sparticuzChromium.setGraphicsMode = false;
export const handler: Handler = async (event, context) => {
let browser;
try {
const executablePath = await sparticuzChromium.executablePath();
browser = await chromium.launch({
args: sparticuzChromium.args,
executablePath,
headless: sparticuzChromium.headless,
});
const context = await browser.newContext();
const page = await context.newPage();
await page.goto('https://talto.cc/');
const locators = await page.locator('section ul li').all();
const promises = locators.map(async (locator) => {
const elment = await locator.elementHandle();
const imgElement = await elment?.$('img');
if (!imgElement) return;
const alt = await imgElement.getAttribute('alt');
if (!alt) return;
console.log(alt);
});
await Promise.all(promises);
} catch (e) {
console.error(e);
throw e;
} finally {
if (browser) await browser.close();
}
};
デプロイ
テスト実行
コンソールからテスト実行を行った。
今回のplaywrightは https://talto.cc/ のトップの新着シナリオの名前を取得するコードとなっている。
Lambdaのログに下記が出力されており、成功したことが確認できた。
START RequestId: 063e5b24-735e-45d6-a7aa-5ad74648879f Version: $LATEST
2023-11-08T13:45:58.005Z 063e5b24-735e-45d6-a7aa-5ad74648879f INFO 第二次遍歴遠征異聞:開かれたる館
2023-11-08T13:45:58.020Z 063e5b24-735e-45d6-a7aa-5ad74648879f INFO 邂逅する真像
2023-11-08T13:45:58.021Z 063e5b24-735e-45d6-a7aa-5ad74648879f INFO 怪談白物語シナリオ 『カッパの手』
2023-11-08T13:45:58.022Z 063e5b24-735e-45d6-a7aa-5ad74648879f INFO 怪談白物語シナリオ 『アパートの壁』
2023-11-08T13:45:58.022Z 063e5b24-735e-45d6-a7aa-5ad74648879f INFO スレイヤー・オブ・ドラゴンスレイヤー 或いは少女リサと雨降りな日々
2023-11-08T13:45:58.024Z 063e5b24-735e-45d6-a7aa-5ad74648879f INFO 『キャスリング ☆ すぴりっと』
2023-11-08T13:45:58.024Z 063e5b24-735e-45d6-a7aa-5ad74648879f INFO マシュマロプラネット
2023-11-08T13:45:58.024Z 063e5b24-735e-45d6-a7aa-5ad74648879f INFO 白雷 -ハクライ-
2023-11-08T13:45:58.025Z 063e5b24-735e-45d6-a7aa-5ad74648879f INFO 新約・きさらぎ駅
2023-11-08T13:45:58.025Z 063e5b24-735e-45d6-a7aa-5ad74648879f INFO おっと!!そっちは二次創作のKPCだ
2023-11-08T13:45:58.042Z 063e5b24-735e-45d6-a7aa-5ad74648879f INFO 客演裁判 スクランブる逆転
2023-11-08T13:45:58.043Z 063e5b24-735e-45d6-a7aa-5ad74648879f INFO Twins
2023-11-08T13:45:58.043Z 063e5b24-735e-45d6-a7aa-5ad74648879f INFO banner
2023-11-08T13:45:58.044Z 063e5b24-735e-45d6-a7aa-5ad74648879f INFO banner
END RequestId: 063e5b24-735e-45d6-a7aa-5ad74648879f
REPORT RequestId: 063e5b24-735e-45d6-a7aa-5ad74648879f Duration: 9592.31 ms Billed Duration: 9593 ms Memory Size: 1024 MB Max Memory Used: 769 MB Init Duration: 450.23 ms
設定ミスで起きたエラーのメモ
chromiumがない
ERROR [Error: Executable doesn't exist at /home/sbx_user1051/.cache/ms-playwright/chromium-1084/chrome-linux/chrome
╔═════════════════════════════════════════════════════════════════════════╗
║ Looks like Playwright Test or Playwright was just installed or updated. ║
║ Please run the following command to download new browsers: ║
║ ║
║ npx playwright install ║
║ ║
║ <3 Playwright Team ║
╚═════════════════════════════════════════════════════════════════════════╝]
ERROR [Error: ENOENT: no such file or directory, open '/var/task/bin/chromium.br'] {
errno: -2,
code: 'ENOENT',
syscall: 'open',
path: '/var/task/bin/chromium.br'
}
ERROR [Error: spawn ETXTBSY
=========================== logs ===========================
<launching> /tmp/chromium --disable-field-trial-config --disable-background-networking --enable-features=NetworkService,NetworkServiceInProcess --disable-background-timer-throttling --disable-backgrounding-occluded-windows --disable-back-forward-cache --disable-breakpad --disable-client-side-phishing-detection --disable-component-extensions-with-background-pages --disable-component-update --no-default-browser-check --disable-default-apps --disable-dev-shm-usage --disable-extensions --disable-features=ImprovedCookieControls,LazyFrameLoading,GlobalMediaControls,DestroyProfileOnBrowserClose,MediaRouter,DialMediaRouteProvider,AcceptCHFrame,AutoExpandDetailsElement,CertificateTransparencyComponentUpdater,AvoidUnnecessaryBeforeUnloadCheckSync,Translate --allow-pre-commit-input --disable-hang-monitor --disable-ipc-flooding-protection --disable-popup-blocking --disable-prompt-on-repost --disable-renderer-backgrounding --force-color-profile=srgb --metrics-recording-only --no-first-run --enable-automation --password-store=basic --use-mock-keychain --no-service-autorun --export-tagged-pdf --disable-search-engine-choice-screen --headless --hide-scrollbars --mute-audio --blink-settings=primaryHoverType=2,availableHoverTypes=2,primaryPointerType=4,availablePointerTypes=4 --no-sandbox --autoplay-policy=user-gesture-required --disable-background-networking --disable-background-timer-throttling --disable-backgrounding-occluded-windows --disable-breakpad --disable-client-side-phishing-detection --disable-component-update --disable-default-apps --disable-dev-shm-usage --disable-domain-reliability --disable-extensions --disable-features=AudioServiceOutOfProcess --disable-hang-monitor --disable-ipc-flooding-protection --disable-notifications --disable-offer-store-unmasked-wallet-cards --disable-popup-blocking --disable-print-preview --disable-prompt-on-repost --disable-renderer-backgrounding --disable-setuid-sandbox --disable-speech-api --disable-sync --disk-cache-size=33554432 --hide-scrollbars --ignore-gpu-blacklist --metrics-recording-only --mute-audio --no-default-browser-check --no-first-run --no-pings --no-sandbox --no-zygote --password-store=basic --use-gl=swiftshader --use-mock-keychain --single-process --user-data-dir=/tmp/playwright_chromiumdev_profile-YJz7Hd --remote-debugging-pipe --no-startup-window
============================================================]
============================================================]
ERROR Error: The input directory "/var/bin" does not exist.
at Chromium.executablePath (/var/task/index.js:68049:17)
at Runtime.handler (/var/task/index.js:68135:52)
at Runtime.handleOnceNonStreaming (file:///var/runtime/index.mjs:1173:29)
ヘッドレスブラウザの設定不足
ERROR [ValidationError: headless: expected boolean, got string]
参考
@sparticuz/chromium
chrome-aws-lambda-layer
playwright
これだけはおさえておきたいPlaywrightコマンド集
2020年: PuppeteerとPlaywrightの激動の1年。