[[Lightpanda]]というものを知ったので、[[Playwright]]で[[Chromium]]とどれくらい差が出るかを試してみた。結論から言うと[[Playwright]]にはまだ対応されていなそうで動かなかった。 ## プロジェクト作成 [[Playwright]]のプロジェクトを[[toki]]で作成する。 ```console toki playwright lightpanda-sandbox ``` ## テストコードを書く [[Minerva]]にアクセスするテストケースを書いてみる。 ```ts import { type Locator, type Page, expect, test } from "@playwright/test"; async function カードリンクをクリック(page: Page, title: string) { await test.step( `カードリンクをクリック "${title}"`, async () => { await page.locator(`[data-href="${title}"]`).click(); }, { box: true }, ); } async function backlinkが表示されていること(page: Page) { await test.step( "backlinkが表示されていること", async () => await expect( page.getByRole("link", { name: "📰ググってヒットしたNeovimプラグイン数", exact: true, }), ).toBeVisible(), { box: true }, ); } async function n番目のリンク先に移動して1段落目の文章を取得する( page: Page, index: number, links: Locator, ) { await test.step( `${index + 1}番目のリンク`, async () => { await test.step("移動", async () => { await backlinkが表示されていること(page); await links.nth(index).click(); await expect(page.getByText("作成:20")).toBeVisible(); }); await test.step("1段落目の文章取得", async () => { const text = await page.locator("p").first().textContent(); console.log(text); }); await test.step("戻る", async () => { await page.goBack(); }); }, { box: true }, ); } test("Minerva test case", async ({ page }) => { await page.goto("https://minerva.mamansoft.net/Home"); await test.step( "Vim駅伝のページまで移動", async () => { await カードリンクをクリック(page, "📒Articles"); await カードリンクをクリック(page, "📒2024 Articles"); await カードリンクをクリック(page, "📘2024年 Neovim成長日記"); await page .getByRole("link", { name: "Vim駅伝", exact: true }) .first() .click(); await backlinkが表示されていること(page); }, { box: true }, ); await test.step("Weekly Report以外のbacklink先に移動し、1段落目の文章を取得", async () => { const links = page .locator(".backlinks") .getByRole("link") .filter({ hasNotText: "Weekly Report" }); const linkNum = await links.count(); for (let i = 0; i < linkNum; i++) { await n番目のリンク先に移動して1段落目の文章を取得する(page, i, links); } }); }); ``` ## Chromiumで実行 以下の条件でそれぞれ3回実行。 | 条件 | 1回目 | 2回目 | 3回目 | | -------- | ----- | ----- | ----- | | headed | 11.3s | 10.5s | 10.8s | | headless | 10.9s | 9.1s | 9.1s | 流石にheadlessの方が少し速い。 ## Lightpandaのインストール [[Lightpanda]]をインストールする。 <div class="link-card-v2"> <div class="link-card-v2-site"> <img class="link-card-v2-site-icon" src="https://github.githubassets.com/favicons/favicon.svg" /> <span class="link-card-v2-site-name">GitHub</span> </div> <div class="link-card-v2-title"> GitHub - lightpanda-io/browser: Lightpanda: the headless browser designed for AI and automation </div> <div class="link-card-v2-content"> Lightpanda: the headless browser designed for AI and automation - lightpanda-io/browser </div> <img class="link-card-v2-image" src="https://opengraph.githubassets.com/8c1ad9756b278b561363a16cfe2b0112c6b277acd4e0df6ce27be506ce63313e/lightpanda-io/browser" /> <a href="https://github.com/lightpanda-io/browser"></a> </div> ```console $ wget https://github.com/lightpanda-io/browser/releases/download/nightly/lightpanda-x86_64-linux $ chmod a+x ./lightpanda-x86_64-linux ``` ```console ./lightpanda-x86_64-linux --host 127.0.0.1 --port 9222 ``` ## テストを実行してみたがPlaywrightには未対応ぽい testを以下のように `ws://localhost:9222` を使うように書き換えてみた。 ```ts test("Minerva test case", async ({ playwright }) => { const browser = await playwright.chromium.connectOverCDP( "ws://localhost:9222", ); const context = await browser.newContext(); const page = await context.newPage(); await test.step("Minervaのトップページに移動", async () => { await page.goto("https://minerva.mamansoft.net/Home"); }); await test.step( "Vim駅伝のページまで移動", async () => { await カードリンクをクリック(page, "📒Articles"); await カードリンクをクリック(page, "📒2024 Articles"); await カードリンクをクリック(page, "📘2024年 Neovim成長日記"); await page .getByRole("link", { name: "Vim駅伝", exact: true }) .first() .click(); await backlinkが表示されていること(page); }, { box: true }, ); await test.step("Weekly Report以外のbacklink先に移動し、1段落目の文章を取得", async () => { const links = page .locator(".backlinks") .getByRole("link") .filter({ hasNotText: "Weekly Report" }); const linkNum = await links.count(); for (let i = 0; i < linkNum; i++) { await n番目のリンク先に移動して1段落目の文章を取得する(page, i, links); } }); }); ``` しかしエラーになる。 ```console $ pnpm exec playwright test Running 1 test using 1 worker 1) [chromium] › tests/example.spec.ts:54:5 › Minerva test case ─────────────────────────────────── Error: Assertion error Error: Assertion error Failed worker ran 1 test: [chromium] › tests/example.spec.ts:54:5 › Minerva test case 1 failed [chromium] › tests/example.spec.ts:54:5 › Minerva test case ──────────────────────────────────── 1 error was not a part of any test, see above for details Serving HTML report at http://localhost:9323. Press Ctrl+C to quit. ``` 該当箇所。 ``` 54 | test("Minerva test case", async ({ playwright }) => { 55 | const browser = await playwright.chromium.connectOverCDP( | ^ 56 | "ws://localhost:9222", ``` [[ChatGPT]]で[[o3-mini-high]]に聞いてみたところ、[[Lightpanda]]の `/json/version` から返却される[[JSON]]が[[Playwright]]のチェックに引っかかっているのではないかとのこと。 <div class="link-card-v2"> <div class="link-card-v2-site"> <img class="link-card-v2-site-icon" src="https://cdn.oaistatic.com/assets/favicon-o20kmmos.svg" /> <span class="link-card-v2-site-name">ChatGPT</span> </div> <div class="link-card-v2-title"> ChatGPT - Lightpanda Browser Playwright エラー </div> <div class="link-card-v2-content"> Shared via ChatGPT </div> <img class="link-card-v2-image" src="https://cdn.oaistatic.com/assets/chatgpt-share-og-u7j5uyao.webp" /> <a href="https://chatgpt.com/share/679f3f9b-f27c-800a-b579-eedd75b85e09"></a> </div> ```console $ curl "http://localhost:9222/json/version" {"webSocketDebuggerUrl": "ws://127.0.0.1:9222/"} ``` 加えて、[[Playwright]]では `assertion error` になって動かない旨のissueもある。 <div class="link-card-v2"> <div class="link-card-v2-site"> <img class="link-card-v2-site-icon" src="https://github.githubassets.com/favicons/favicon.svg" /> <span class="link-card-v2-site-name">GitHub</span> </div> <div class="link-card-v2-title"> Playwright CDP connection fails with assertion error · Issue #363 · lightpanda-io/browser </div> <div class="link-card-v2-content"> When connecting to browser using Playwright's Python CDP interface, connection is immediately closed with an ass ... </div> <img class="link-card-v2-image" src="https://opengraph.githubassets.com/a2045828fd691f4b7f697afbd9fd106c425a6a83239b27c848b77c34f3a14c02/lightpanda-io/browser/issues/363" /> <a href="https://github.com/lightpanda-io/browser/issues/363"></a> </div>