サイトアイコン TakeNotes.JP

Playwrightを使ったブラウザ操作自動化

Playwrightを説明する必要にかられて作成。

なお、本記事の利用用途はE2Eテストではなく、ただのブラウザ操作自動化です。

前提としてNode.js 12以上が必要です。そちらの説明は「NVM for Windowsを使って複数バージョンのnodejsをインストール」をご覧ください。

前準備

実験用にtest-playwrightディレクトリを作ります。今後はこのディレクトリで作業します。

>mkdir test-playwright && cd test-playwright

Playwrightのインストール

npmを使ってインストール

>npm install playwright

added 2 packages in 2s

package.jsonやnode_modulesディレクトリなどが生成されます。

バージョン確認

>npx playwright --version
Version 1.31.2

Playwrightのデモ

Yahoo! JAPANを開く

> npx playwright codegen "https://www.yahoo.co.jp"

Yahoo! Japanを開いた状態でChromium とPlaywright Inspector の2つが起動

Playwright Inspectorウィンドウの Target: 「Test Runner」を「Library」に変更

Chromium(Yahoo! Japan)を以下の手順でマウス操作してみます。

  1. 検索フォームから「Google」とタイプして検索
  2. 検索結果からGoogleをクリック
  3. Googleの検索フォームに「Yahoo」とタイプして検索
  4. Googleの検索結果からYahoo! JAPANをクリック

上記の手順が済んだらPlaywright Inspectorで生成されたコードを確認

※Chromiumを閉じるとPlaywright Inspectorまで一緒に閉じてしまうので注意

出来上がったコード(下記参照)をコピーし、yahoo.cjs と名付けてUTF-8で保存

const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch({
    headless: false
  });
  const context = await browser.newContext();
  const page = await context.newPage();
  await page.goto('https://www.yahoo.co.jp/');
  await page.getByRole('searchbox', { name: '検索したいキーワードを入力してください' }).click();
  await page.getByRole('searchbox', { name: '検索したいキーワードを入力してください' }).fill('Google');
  await page.getByRole('button', { name: '検索' }).click();
  await page.getByRole('link', { name: 'Google https://www.google.com ...' }).click();
  await page.getByRole('combobox', { name: '検索' }).click();
  await page.getByRole('combobox', { name: '検索' }).fill('Yahoo');
  await page.getByRole('combobox', { name: '検索' }).press('Enter');
  await page.getByRole('link', { name: 'Yahoo! JAPAN Yahoo! JAPAN https://www.yahoo.co.jp' }).click();

  // ---------------------
  await context.close();
  await browser.close();
})();

上記コードを実行

>node yahoo.cjs

Chromiumが立ち上がり、「Yahoo検索→Google検索→Yahooへ」の操作を自動で行う

スクリーンショットを撮る1行を追加

const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch({
    headless: false
  });
  const context = await browser.newContext();
  const page = await context.newPage();
  await page.goto('https://www.yahoo.co.jp/');
  await page.getByRole('searchbox', { name: '検索したいキーワードを入力してください' }).click();
  await page.getByRole('searchbox', { name: '検索したいキーワードを入力してください' }).fill('Google');
  await page.getByRole('button', { name: '検索' }).click();
  await page.getByRole('link', { name: 'Google https://www.google.com ...' }).click();
  await page.getByRole('combobox', { name: '検索' }).click();
  await page.getByRole('combobox', { name: '検索' }).fill('Yahoo');
  await page.getByRole('combobox', { name: '検索' }).press('Enter');
  await page.getByRole('link', { name: 'Yahoo! JAPAN Yahoo! JAPAN https://www.yahoo.co.jp' }).click();
  // ここに1行追加しました
  await page.screenshot({ path : 'yahoo.png'});
  // ---------------------
  await context.close();
  await browser.close();
})();

ちなみに、以下のコメントアウトした部分がなくても動きます(マウスのために入った余計な操作なので)

const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch({
    headless: false
  });
  const context = await browser.newContext();
  const page = await context.newPage();
  await page.goto('https://www.yahoo.co.jp/');
  //await page.getByRole('searchbox', { name: '検索したいキーワードを入力してください' }).click();
  await page.getByRole('searchbox', { name: '検索したいキーワードを入力してください' }).fill('Google');
  await page.getByRole('button', { name: '検索' }).click();
  await page.getByRole('link', { name: 'Google https://www.google.com ...' }).click();
  //await page.getByRole('combobox', { name: '検索' }).click();
  await page.getByRole('combobox', { name: '検索' }).fill('Yahoo');
  await page.getByRole('combobox', { name: '検索' }).press('Enter');
  await page.getByRole('link', { name: 'Yahoo! JAPAN Yahoo! JAPAN https://www.yahoo.co.jp' }).click();
  await page.screenshot({ path : 'yahoo.png'});
  // ---------------------
  await context.close();
  await browser.close();
})();

headless: falseをtrueに変更するとヘッドレスモード(Chromiumを画面非表示)で実行

const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch({
  // ここです
    headless: true
  });
  const context = await browser.newContext();
  const page = await context.newPage();
  await page.goto('https://www.yahoo.co.jp/');
  //await page.getByRole('searchbox', { name: '検索したいキーワードを入力してください' }).click();
  await page.getByRole('searchbox', { name: '検索したいキーワードを入力してください' }).fill('Google');
  await page.getByRole('button', { name: '検索' }).click();
  await page.getByRole('link', { name: 'Google https://www.google.com ...' }).click();
  //await page.getByRole('combobox', { name: '検索' }).click();
  await page.getByRole('combobox', { name: '検索' }).fill('Yahoo');
  await page.getByRole('combobox', { name: '検索' }).press('Enter');
  await page.getByRole('link', { name: 'Yahoo! JAPAN Yahoo! JAPAN https://www.yahoo.co.jp' }).click();
  await page.screenshot({ path : 'yahoo.png'});
  // ---------------------
  await context.close();
  await browser.close();
})();

ざっくりこんな感じ

const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch({
    headless: true
  });
  const context = await browser.newContext();
  const page = await context.newPage();
  await page.goto('https://www.example.jp/');
  // ここからやりたいことを書く

  フォームを入力したり、プルダウンから選択したり
  スクリーンショットを撮ったり、ボタンを押したり

  // ここまで
  await browser.close();
})();

codegenで作成したコードのため、『「検索」ボタンをクリック』のような記述になっていますが、本来はdata-testid属性を用いて、HTML側で<button data-testid="search">検索</button> Playwright側でawait page.getByTestId('search').click();とする記述が望ましいようです。

参考

モバイルバージョンを終了