Playwright
クイックスタート
1. 概要
Playwright は Microsoft が開発した、Web アプリ向けの自動化テストフレームワークです。
Playwright は NodeJS と Python で書けます。
Selenium との違い
- Selenium は Web 自動化機能だけを提供します。自動化テストを行う場合、他の自動化テストフレームワークと組み合わせる必要があります。一方、Playwright は自動化テスト向けで、Web 自動化機能のほかに、自動化テストの機能フレームワークも含みます。
- 両者の自動化原理には違いがあります。
2. インストール
pip install playwright次の情報が表示されれば、インストール完了です。
C:\Windows\system32>pip install playwright
Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple/
Collecting playwright
Downloading https://pypi.tuna.tsinghua.edu.cn/packages/46/4f/9ba607fa94bb9cee3d4beb1c7b32c16efbfc9d69d5037fa85d10cafc618b/playwright-1.55.0-py3-none-win_amd64.whl (35.5 MB)
---------------------------------------- 35.5/35.5 MB 6.1 MB/s eta 0:00:00
Collecting pyee<14,>=13 (from playwright)
Downloading https://pypi.tuna.tsinghua.edu.cn/packages/9b/4d/b9add7c84060d4c1906abe9a7e5359f2a60f7a9a4f67268b2766673427d8/pyee-13.0.0-py3-none-any.whl (15 kB)
Collecting greenlet<4.0.0,>=3.1.1 (from playwright)
Downloading https://pypi.tuna.tsinghua.edu.cn/packages/d8/0f/30aef242fcab550b0b3520b8e3561156857c94288f0332a79928c31a52cf/greenlet-3.2.4-cp311-cp311-win_amd64.whl (299 kB)
---------------------------------------- 299.1/299.1 kB 6.1 MB/s eta 0:00:00
Collecting typing-extensions (from pyee<14,>=13->playwright)
Downloading https://pypi.tuna.tsinghua.edu.cn/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl (44 kB)
---------------------------------------- 44.6/44.6 kB ? eta 0:00:00
Installing collected packages: typing-extensions, greenlet, pyee, playwrightPlaywright をインストールした後、次のコマンドでブラウザをインストールします。
playwright install chromium3. 自動化コードアシスタント
Playwright にはコードアシスタントが内蔵されており、コードを自動生成できます。 次のコマンドを入力すると、コードアシスタントを起動できます。
playwright codegen注意:コードアシスタントは主に人のページ入力を記録します。自分で書くコードの代わりにはなりません。特にページ上の情報を取得するコードは自動生成できません(例:タイトルバーを出力するコード)。
page.wait_for_timeout(1000) の単位は ms です。
4. トレース機能
Playwright には特徴的な機能として tracing があります。 tracing を起動すると、自動化実行後に、記録されたトレースデータファイルを使って、自動化中の各細部を見返せます。
実行完了後、現在の作業ディレクトリに trace.zip というトレースデータファイルが生成されます。 このファイルを見る方法は二つあります。
https://trace.playwright.dev/に直接アクセスし、トレースファイルをアップロードします。playwright show-trace trace.zipを実行し、ローカルで開きます。
位置指定
Web 画面を自動化して画面を操作するには、まず画面要素を位置指定する必要があります。 ブラウザに先に要素を見つけさせることで、その後に要素を操作できます。
相対的に、要素の位置指定は後続の操作より難しいです。よくある操作は多くなく、固定された呼び出しが多いからです。
例:
- 要素をクリックする:
click() - テキストを入力する:
fill() - 要素内部テキストを取得する:
inner_text()
Locator オブジェクト
Playwright で CSS Selector によって要素を位置指定する時は、Locator オブジェクトを使います。
Page オブジェクトの locator メソッドは Locator 型のオブジェクトを作成します。パラメータには CSS Selector 式を指定できます。
page.locator("div") # div 要素
page.locator("#myId") # id が myId の要素
page.locator(".myClass") # class が myClass の要素tag 名、id、class で要素を位置指定する
CSS Selector は HTML 要素のタグ名、id、class によって位置指定できます。
tag 名で要素を選択する場合、tag 名をそのまま書けます。たとえば tag 名が div のすべての要素を選ぶ場合:
locators = page.locator("div").all()その後、すべての div 要素の内部可視テキストを取得できます。all_inner_texts を直接呼び出せます。
for one in locators:
print(one.inner_text())すべての div 要素の内部可視テキストは、チェーン呼び出しでも取得できます。
texts = page.locator("div").all_inner_texts()注意:
locator呼び出しの結果が複数要素に一致する場合、単一要素向けのメソッド、たとえばinner_textを呼ぶとエラーが発生します:page.locator('div').inner_text()
一つの要素は複数の class を持てます。複数の class の値は空白で区切ります。例:
<span class="chinese student">張三</span>注意:この span タグには二つの class 属性値があります。chinese と student であり、chinese student ではありません。 コードでこの要素を選ぶ時は、どちらか一つの class 属性値を指定すれば一致します。
次のようには書けません。
page.locator(".chinese student")二つの class 属性を同時に持つことを表す場合は、次のように書きます。
page.locator(".chinese.student")二種類の class 属性のどちらかを選ぶ場合は、次のように書きます。
page.locator(".chinese,.student")CSS Selector が正しく要素を選んでいるか確認する
Python コードを書いて実行し、正しく要素を選べたか確認できます。しかし面倒です。
ブラウザの開発者ツールで直接確認できます。
- 開発者ツールを開きます。
ElementsタブでCtrl + Fを同時に押し、検索ボックスを開きます。この検索ボックスは CSS Selector の書き方をサポートしています。
複数要素に一致する場合
一つの locator 式が複数要素に一致する場合、すべての要素の locator オブジェクトを取得するには all() メソッドを使います。
locators = page.locator(".plant").all()ある式に対応する要素数だけが必要な場合は、count() メソッドを使えます。
count = page.locator(".plant").count()結果、つまり一致した要素数により、要素が存在するか判断できます。
最初に一致した要素、または最後の要素だけが必要な場合もあります。 first と last 属性を使えます。
lct = page.locator(".plant")
print(lct.first().inner_text(), lct.last().inner_text())nth メソッドでインデックスを指定し、何番目の要素かを取得することもできます。
lct = page.locator(".plant")
print(lct.nth(0).inner_text(), lct.nth(1).inner_text())要素内部で位置指定する
前の例はすべて Page オブジェクトから locator メソッドを呼び出しており、範囲は Web ページ全体です。 ある要素の内部で位置指定したい場合は、Locator オブジェクトから locator メソッドを呼び出します。
# #bottom に対応する要素の範囲内で、tag 名が span の要素を探す
lct = page.locator("#bottom")
eles = lct.locator("span").all()
for e in eles:
print(e.inner_text())子要素と子孫要素を選ぶ
HTML では、要素内部に他の要素を含められます。 要素2が要素1の直接の子要素である場合、CSS Selector で子要素を選ぶ構文は次の通りです。
要素1 > 要素2最終的に選ばれる要素は要素2です。
要素2が要素1の子孫要素である場合、CSS Selector で子孫要素を選ぶ構文は次の通りです。
要素1 要素2最終的に選ばれる要素は要素2です。
属性で要素を選ぶ
CSS Selector は要素の属性によって要素を選べます。 構文は角括弧 [] です。
たとえば a 要素を選びます。
<a href="https://www.baidu.com">百度</a>href 属性が https://www.baidu.com の a 要素を選ぶ場合、次を使います。
[href='https://www.baidu.com']タグ制限を付けることもできます。
a[href='https://www.baidu.com']属性で選ぶ時、属性値を指定しないこともできます。
[href]CSS は属性値がある文字列を含む要素も選べます。
a[href*="baidu"]属性値がある文字列で始まる要素も選べます。
a[href^="https"]属性値がある文字列で終わる要素も選べます。
a[href$="com"]複数属性を指定することもできます。
a[href*="baidu"][title="百度"]順番で子ノードを選ぶ
CSS Selector は、ある要素の何番目の子ノードを選べます。 構文は次の通りです。
要素:nth-child(n)
nは整数で、何番目の子ノードかを表します。nは 1 から数えます。
たとえば、div 要素の 2 番目の子要素を選びます。
div:nth-child(2)div 要素の 2 番目の子要素で、かつその子要素が span 要素である場合は、次のように書きます。
div > span:nth-child(2)後ろから何番目の子要素かを選ぶこともできます。
div:nth-last-child(2)親ノードを選ぶ
隣接兄弟要素を選ぶ
XPath 位置指定
XPath(XML Path Language)は W3C が公開した、XML と HTML 文書内でノードを選択するための言語です。 Playwright も XPath による要素位置指定をサポートしています。
Playwright コードアシスタントが生成する位置指定
Playwright は CSS Selector による位置指定をすすめていません。CSS Selector は HTML ページ要素の特徴に基づく位置指定で、開発者視点です。 Playwright は、ユーザー視点の視覚的な表示に基づく位置指定をよりすすめています。
テキスト内容で位置指定する
ページ内に特定の文字を含む要素を取得したい場合、CSS Selector では面倒なことがあります。Page/Locator オブジェクトの get_by_text メソッドを使えます。
# 百度一下 という文字を持つすべての要素を選ぶ
elements = page.get_by_text("百度一下").all()文字一致には正規表現も使えます。たとえば 下 で終わる文字の要素を一致させます。
import re
elements = page.get_by_text(re.compile("百度一下$")).all()Role で位置指定する
Web アプリには ARIA(Accessible Rich Internet Applications) という標準があります。 ARIA は Web ページ内の各種要素の役割を定義します。例:ボタン、リンク、画像、テキスト、入力欄など。 Playwright は ARIA role によって要素を位置指定する方法を提供しています。
# すべてのボタンを選ぶ
elements = page.get_by_role("button").all()よく使う視覚位置指定
placeholder 属性で位置指定します。 Page/Locator オブジェクトの get_by_placeholder メソッドを使えます。
<input type=""text placeholder="captcha"/>page.get_by_placeholder("captcha",exact=True) # 完全一致を表すその他の視覚位置指定
label で位置指定できます。
page.get_by_label("username").fill("ttp")操作
デフォルト待機時間
Playwright が要素を位置指定する時、要素が見つからなくてもすぐにエラーを投げません。デフォルトでは 30 秒待ちます。30 秒以内に要素が現れれば、すぐに操作成功として返ります。
要素の共通操作
テキスト内容を取得する Locator オブジェクトの
inner_text()メソッドで内部テキストを取得できます。 locator が複数要素を選んだ場合は、all_inner_texts()を使い、すべての一致テキストをリストとして返せます。 この二つのメソッドが返すのは、要素内部の可視テキストです。隠れた内容を取得する
text_content()またはall_text_contents()メソッドで、単一または複数の一致対象のテキストを取得できます。要素の属性を取得する 要素の属性値は、Locator オブジェクトの
get_attribute('属性名')メソッドで取得できます。要素内部 HTML を取得する Locator オブジェクトの
inner_html()メソッドを使います。要素が見えるまで待つ
wait_for()で要素の出現を待ちます。要素が見えるか判断する 自動化コードでは、現在ページに
特定内容が存在するかによって次の操作を決めることがあります。 この時はis_visible()メソッドを使えます。
このメソッドは要素の出現を待たず、直接 true または false を返します。
カーソル操作
クリック
click()メソッドは要素を単クリックします。ダブルクリックにはdbclick()を使えます。ホバー カーソルをある要素の上に置くには、
hover()メソッドを使えます。
入力欄操作
テキスト入力 一行テキストボックス
inputまたは複数行テキストボックスtextareaは、Locator オブジェクトのfileメソッドで入力できます。テキストボックスを空にする 一行テキストボックスや複数行テキストボックスの内容を消すには、
clearメソッドを使います。
注意:
input欄の内容を取得するには、input_value()メソッドを使います。
- ファイル入力欄 HTML にファイル型の入力欄がある場合、通常はファイルアップロードに使います。 選択するファイルを設定するには、locator オブジェクトの
set_input_files()メソッドを使います。
page.locator('input[type=file]')
# 単一選択
lc.set_input_files('d:/1.png')
# 複数選択
lc.set_input_files(['d:/1.png','d:/2.png'])- radio 単選択 / checkbox 複数選択 よくある選択欄には radio、checkbox、select があります。 radio はよく使う
クリック選択要素です。
<div id="s _radio">
<input type="radio" name="teacher" value="山田先生">山田先生<br>
<input type="radio" name="teacher" value="佐藤先生">佐藤先生<br>
<input type="radio" name="teacher" value="鈴木先生" checked="checked">鈴木先生
</div>radio ボックスを選択するには check() メソッドを使います。 radio ボックスの選択を解除するには uncheck() メソッドを使います。 radio ボックスが選択されているか判断するには is_checked() メソッドを使います。
checkbox も radio と同じです。
- select ボックス select 要素に対応する
select_optionメソッドを使えます。 単選択ボックスの場合:
page.locator('#ss_single').select_option('山田先生')ここで
select_optionパラメータは、選択肢option要素のvalueまたは選択肢テキストと完全一致する必要があります。
キーワードパラメータ、index、value、label を使い、それぞれインデックス、value 属性、選択肢テキストで一致させることもできます。
# インデックスで選択。0から始まる
page.locator('#ss_single').select_option(index=1)
# value 属性で選択
page.locator('#ss_single').select_option(value='山田先生')
# 選択肢テキストで選択
page.locator('#ss_single').select_option(label='山田先生')
# すべての選択を消す
page.locator('#ss_single').select_option([])select 複数選択ボックスも、方法は上と同じです。パラメータをリストに変えるだけです。
page.locator('#ss_single').select_option(value=['山田先生','田中先生'])Web ページへの操作
URL を開く / 更新 / 戻る / 進む: 開く/更新/戻る/進むには、Page オブジェクトの goto/reload/go_back/go_forward メソッドをそれぞれ呼び出します。
Web ページ HTML を取得する: ページ全体の html を取得するには、Page の content() メソッドを呼び出します。
title: ページ全体のタイトルバー文字を取得するには、Page オブジェクトの title() メソッドを呼び出します。
set-viewport-size: ページサイズを設定するには、Page オブジェクトの set_viewport_size メソッドを呼び出します。
# 単位はピクセル
page.set_viewport_size({"width": 640,"height": 480})frame 切り替え
Web ページは別の Web ページを埋め込めます。ただし Playwright でページを開いた時、操作範囲のデフォルトは現在の html であり、埋め込まれた html 文書の内容は含みません。埋め込まれた html 文書内の要素を位置指定して操作したい場合は、操作範囲をその文書へ切り替える必要があります。 Page または Locator オブジェクトの frame_locator() メソッドで、操作したい frame を位置指定できます。
# Frame locator オブジェクトを生成
frame = page.frame_locator("iframe[src='sample1.html']")
# その内部で位置指定する
lcs = frame.locator('.plant').a11()
for lc in lcs:
print(lc.inner_text(timeout=1000))ウィンドウ切り替え
a リンクをクリックすると、別の Web ページへ移動したり、別ウィンドウを開いたりできます。 新しいウィンドウが開いても、この時の Page 変数は古いウィンドウに対応しています。自動化操作も古いウィンドウで行われるため、新しいウィンドウへ切り替える必要があります。 BrowserContext オブジェクトには pages 属性があり、すべてのウィンドウに対応する Page オブジェクトが順番に入っています。
from playwright.sync_api import sync_playwright
pw = sync_playwright().start()
browser = pw.chromium.launch(headless=False)
# BrowserContext オブジェクトを作成
context = browser.new_context()
# context から page を作成
page = context.new_page()
page.goto("https:ur")
# リンクをクリックし、新しいウィンドウを開く
page.locator("a").click()
# 2秒待つ
page.wait_for_timeout(2000)
# pages 属性はすべてのウィンドウのリスト
newPage = context.pages[1]
# 新旧 Web ページのタイトルを表示
print(newPage.title())
print(page.title())多くのウィンドウが開いていて、目標の順番が分からない場合は、タイトルを確認する方法を使えます。
現在の tab を設定する
あるウィンドウを現在のアクティブウィンドウとして表示したい場合、そのウィンドウオブジェクトの bring_to_front() メソッドを呼び出します。
Web ページウィンドウを閉じる
Page オブジェクトの close() メソッドを直接呼び出します。
ウィンドウを停止させる
一部の要素は、カーソルを移動した時だけ表示されます。 コンソールに次を入力できます。
setTimeout(function(){debugger}, 5000)スクリーンショット
Page オブジェクトの screenshot() メソッドを使います。
# 現在ページの可視内容をスクリーンショットし、現在の作業ディレクトリの ss1.png に保存する
page.screenshot(path='ss1.png')
# フルスクリーンショット。ページが長い場合、全体を撮れる
page.screenshot(path='ss1.png',full_page=True)ある要素の表示内容だけをスクリーンショットすることもできます。Locator オブジェクトの screenshot メソッドを使います。
page.locator('input[type=file]').screenshot(path='ss1.png')ドラッグ
Page オブジェクトの drag_and_drop() メソッドを使えます。 たとえば span #t1 のテキスト内容を選択し、入力欄へドラッグします。
page.locator('#t1').select_text()
page.drag_and_drop('#t1', '[placeholder="captcha"]')ダイアログ
ポップアップダイアログには三つの種類があります。alert(警告情報)、confirm(確認情報)、prompt(入力提示)です。
Alert
alert は通知情報です。ユーザーが情報を見た後、ok をクリックすればよいです。
# ポップアップダイアログを処理する関数
def handleDlg(dialog):
page.wait_for_timeout(1000)
# 確認をクリック
dialog.accept()
print(dialog.message)
# ポップアップダイアログイベントのコールバック関数を設定
page.on("dialog", handleDlg)Confirm
accept() メソッドは確認クリックに相当します。 dismess() はキャンセルクリックに相当します。
Prompt
accept() メソッドに文字列パラメータを入力し、入力する情報として使います。
dialog.accept("入力する内容")