Loading...

2024-03-04(月) 16:00

🦾 Playwrghtを使用してブラウザ操作を自動化する

Node.jsPlaywright
Microsoft社が開発、公開しているWebサイトのテスト、操作自動化のためのフレームワークであるPlaywrightを使ってブラウザ操作を自動化する手順を解説します。

目次

前提と注意事項

  • Node.js がインストールされている環境が必要です。
  • Playwright によってアクセスする Web サイトに負荷をかけることのないよう自己責任の元で十分注意してください。

Playwright について

Playwright は、Microsoft 社が開発、公開している Web サイトのテスト、操作自動化のためのフレームワークです。 Chromium、Firefox、WebKit の 3 つのブラウザに対応しており、Linux、Windows、macOS で動作します。Playwright を使うことで Web サイトのテスト、操作自動化を行うことができます。 以下が公式リポジトリです。

🎭 Playwright

Playwright is a framework for Web Testing and Automation. It allows testing Chromium, Firefox and WebKit with a single API. Playwright is built to enable cross-browser web automation that is ever-green, capable, reliable and fast.

github.com

この記事のゴール

この記事では、以下のブラウザ操作を Playwright によって自動化することがゴールです。

  • ページのスクリーンショットを撮る
  • ページの PDF を取得する
  • 認証が必要なページにアクセスしてログインする
  • 指定したページ内にある 特定要素の中の h1 タグのテキスト、リンク先を取得する

Playwright をインストールする

Node.js を実行できる環境で、適当なディレクトリで以下を実行します。ここでは、~/workspace/playwrightというディレクトリで作業を行うとします。

~/workspace/playwright
$ npm init playwright@latest
# または
$ yarn create playwright

以下の様に質問が表示されるので、回答します。

~/workspace/playwright
$ yarn create playwright
? Do you want to use TypeScript or JavaScript? …
 TypeScript
  JavaScript
? Where to put your end-to-end tests? › tests
? Add a GitHub Actions workflow? (y/N) › false
? Install Playwright browsers (can be done manually via 'yarn playwright install')? (Y/n) › true

Chrominum などのブラウザのインストールも始まるため、3分〜5分、もしかするとそれ以上かかるかもしれません。 最終的に以下の様に表示されればインストール完了します。

~/workspace/playwright
 Success! Created a Playwright Test project at /Users/username/workspace/playwright
 
Inside that directory, you can run several commands:
 
  yarn playwright test
    Runs the end-to-end tests.
 
  yarn playwright test --ui
    Starts the interactive UI mode.
 
  yarn playwright test --project=chromium
    Runs the tests only on Desktop Chrome.
 
  yarn playwright test example
    Runs the tests in a specific file.
 
  yarn playwright test --debug
    Runs the tests in debug mode.
 
  yarn playwright codegen
    Auto generate tests with Codegen.
 
We suggest that you begin by typing:
 
    yarn playwright test
 
And check out the following files:
  - ./tests/example.spec.ts - Example end-to-end test
  - ./tests-examples/demo-todo-app.spec.ts - Demo Todo App end-to-end tests
  - ./playwright.config.ts - Playwright Test configuration
 
Visit https://playwright.dev/docs/intro for more information. 
 
Happy hacking! 🎭
  Done in 184.96s.

上記の時点で、~/workspace/playwrightディレクトリには以下のディレクトリ、ファイルが生成されます。

~/workspace/playwright
.
├── .gitignore
├── node_modules
├── package.json
├── playwright.config.ts
├── tests
├── tests-examples
└── yarn.lock

ページのスクリーンショットを撮る

試しに、~/workspace/playwrightの中に test.ts というファイルを作成し、以下の内容を記述します。

~/workspace/playwright/test.ts
import { chromium } from 'playwright-core';
 
(async () => {
  const browser = await chromium.launch({ headless: false }); // ブラウザを起動。headless: false でブラウザを表示する. true で非表示
  const page = await browser.newPage(); // ブラウザで新しいページを開く
 
  await page.goto('https:/ritaiz.com'); // アクセスしたいURLを指定
 
  // スクリーンショットの撮影. fullPage: true でスクロールが必要なページ全体を撮影可
  await page.screenshot({ path: `screenshots/test.png`, fullPage: false });
  await browser.close(); // ブラウザ を閉じる
})();

以下のコマンドでtest.tsを実行します。

~/workspace/playwright
$ npx ts-node test.ts

上記を実行すると、Chrominum が起動して指定した URL にアクセスする様子を確認できると思います。 また、screenshotsディレクトリが作成され、その中にtest.pngというファイルが生成されていることを確認してください。

なお、もしts-nodeがない場合は以下の様に表示されるのでyを入力してインストールしてください。

~/workspace/playwright
$ npx ts-node test.ts
Need to install the following packages:
[email protected]
Ok to proceed? (y) y

ページの PDF を取得する

以下の様にpage.pdfを使うことで PDF を取得できます。

~/workspace/playwright/pdf-test.ts
import { chromium } from 'playwright-core';
 
(async () => {
  const browser = await chromium.launch({
    headless: false,
  });
  const page = await browser.newPage();
  await page.goto('https://ritaiz.com');
  await page.pdf({ path: `screenshots/test.pdf`, format: 'A4' });
  await browser.close();
})();

なお、formatなどのオプションは以下の公式ドキュメントを参照ください。

pdf

Returns the PDF buffer.

playwright.dev

認証が必要なページにアクセスしてログインする

今度はlogin-test.tsというファイルを作成して以下の様にします。

~/workspace/playwright/login-test.ts
import { chromium } from 'playwright-core';
 
(async () => {
  const browser = await chromium.launch({ headless: false });
  const page = await browser.newPage();
 
  await page.goto('https://ritaiz.com/login');
 
  // 「メールアドレス」というラベルを持つ要素を取得し、その要素に対して「[email protected]」を入力する
  await page.getByLabel('メールアドレス').fill('[email protected]');
 
  // 「パスワード」というラベルを持つ要素を取得し、その要素に対して「yourpassword」を入力する
  await page.getByLabel('パスワード').fill('yourpassword');
 
  // 「ログイン」というラベルを持つボタンを取得し、そのボタンをクリックする
  await page.getByRole('button', { name: 'ログイン' }).click();
 
  await page.screenshot({ path: `screenshots/test2.png`, fullPage: true });
  await browser.close();
})();

以下で実行します。

~/workspace/playwright
$ npx ts-node login-test.ts

ログインフォームへの入力とログインボタンのクリックが実行されてログインが完了する様子を確認できると思います。なお、上記で指定しているフォームのラベルやボタンのラベルは、実際のページの HTML に合わせて変更してください。

また、上記ではgetByLabelgetByRoleを使用して操作対象の取得を行いましたが、Playwright には他にも様々なメソッドが用意されています。具体的には、以下の公式ドキュメントを参照ください。

Playwright Page

Page provides methods to interact with a single tab in a Browser, or an extension background page in Chromium. One Browser instance might have multiple Page instances.

playwright.dev

指定したページ内にある 特定要素の中の h1 タグのテキスト、リンク先を取得する

以下の様に、article-cardというクラスが指定されたdiv要素が複数ある HTML を例にします。

使用するHTML
<div class="article-card p-4 border rounded-sm bg-white">
  <a
    href="/articles/integrating-homeassistant-with-switchbot-cloud-to-operate-from-switchbot-hub"
  >
    <div class="flex flex-col">
      <h2
        class="flex text-xs text-gray-500 mb-2 text-left font-bold items-center"
      >
        2024-02-07(水) 06:00
      </h2>
      <div class="rounded-lg">
        <p></p>
      </div>
      <div class="">
        <span class="text-gray-500"></span>
        <h1 class="font-bold text-lg text-black mb-2">
          🎚️ HomeAssistantとSwitchBotクラウドを連携してSwitchBot
          Hub経由の操作を行う
        </h1>
        <span
          class="text-xs font-semibold inline-block py-1 px-2 rounded text-slate-600 bg-slate-200 uppercase last:mr-0 mr-1"
          >Ubuntu</span
        >
        <span
          class="text-xs font-semibold inline-block py-1 px-2 rounded text-slate-600 bg-slate-200 uppercase last:mr-0 mr-1"
          >Docker</span
        >
        <span
          class="text-xs font-semibold inline-block py-1 px-2 rounded text-slate-600 bg-slate-200 uppercase last:mr-0 mr-1"
          >RaspberryPi</span
        >
        <span
          class="text-xs font-semibold inline-block py-1 px-2 rounded text-slate-600 bg-slate-200 uppercase last:mr-0 mr-1"
          >HomeAssistant</span
        >
      </div>
      <div class="text-left text-sm text-gray-600 mt-4">
        Ubuntuで動かしているHomeAssistantをSwithBotクラウドと連携させて、HomeAssistantからSwithBot
        Hub経由での操作を行うところまでの手順を解説します。
      </div>
    </div>
  </a>
</div>
<!-- ...以降、クラスarticle-cardを持つdiv要素が複数あるとします。 -->

上記の場合に、複数あるarticle-cardという class を持つ要素の中にあるh1タグのテキストとaタグのリンク先を取得するには以下の様にします。

~/workspace/playwright/article-test.ts
import { chromium } from 'playwright-core';
 
(async () => {
  const browser = await chromium.launch({
    headless: false,
  });
  const page = await browser.newPage();
  await page.goto('http://localhost:3011/articles');
 
  // class `article-card` がある要素を全て取得
  const articleCards = await page.locator('.article-card').all();
 
  // articleCards に対して Promise を返す関数を作成
  const articlePromises = articleCards.map(async (article) => {
    const title = await article.locator('h1').textContent();
    const url = await article.locator('a').getAttribute('href');
    return { title, url };
  });
 
  // Promise.all で全ての Promise が完了するまで待つ
  const result = await Promise.all(articlePromises);
 
  // 結果を出力
  console.log(result);
 
  await page.waitForTimeout(3000);
  await browser.close();
})();

上記を実行すると以下の結果を得ることができます。

出力結果
[
  {
    title: '🎭 Playwrghtを使用してブラウザ操作を自動化する',
    url: '/articles/automating-browser-operations-using-playwright'
  },
  {
    title: '🎚️ HomeAssistantとSwitchBotクラウドを連携してSwitchBot Hub経由の操作を行う',
    url: '/articles/integrating-homeassistant-with-switchbot-cloud-to-operate-from-switchbot-hub'
  },
  {
    title: '🏠 UbuntuでHomeAssistantをDockerで動かす',
    url: '/articles/steps-to-setup-homeassistant-on-ubuntu-using-docker'
  },
  {
    title: '📆 AutoHotKeyとタスクスケジューラを使ってPower Automate Desktopとスケジュール実行する',
    url: '/articles/using-autohotkey-and-task-scheduler-to-schedule-execution-with-power-automate-desktop'
  },
  {
    title: '⌨️ Windows11でAutoHotKeyを使ってショートカットキーをスクリプトから実行する',
    url: '/articles/executing-shortcut-keys-from-script-using-autohotkey-on-windows11'
  },
  {
    title: '🤖 Next.jsでChatGPTとのチャットフォームを実装する',
    url: '/articles/implement-a-chat-form-with-chatgpt-in-nextjs'
  },
  {
    title: '🦾 ChatGPT APIをセットアップし動作確認する',
    url: '/articles/setup-and-trying-chatgpt-api'
  },
  {
    title: '💿 Synology NASに最新版のTailscaleをインストールする',
    url: '/articles/steps-to-install-latest-tailscale-on-synology-nas'
  },
  {
    title: '🏁 Next.jsでQRコードを生成、ダウンロードできるようにする',
    url: '/articles/implementing-qrcode-generation-and-download-in-nextjs'
  },
  {
    title: '🔍 Next.jsでQRコードリーダーを実装する',
    url: '/articles/implementing-qrcode-scanner-in-nextjs'
  },
  {
    title: '✍️ Power Automate DesktopでSlackにメッセージを投稿する',
    url: '/articles/sending-message-to-slack-using-power-automate-desktop'
  }
]

まとめ

Playwright を使ってブラウザ操作を自動化することで Web アプリのテストや、業務によっては自動化によって大きな効率化を実現できる可能性があります。