HOWTO · Python

Selenium Python の send_keys() メソッド

このチュートリアルでは、Selenium Python で send_keys() メソッドを使用する方法を示します。

このページの内容

send_keys() は Selenium の WebElement に定義されたメソッドで、取得済みの要素(通常はテキストボックス、フォームフィールド、その他の編集可能なコントロール)にテキストやキーボード入力を送信します。要素を取得すれば、element.send_keys("your text") で各文字を入力でき、element.send_keys(Keys.ENTER) で Enter などの名前付きキーを送信できます。フォームへの入力、検索の実行、入力に対するアプリケーションの反応の確認に使う標準的な方法です。

Selenium Python で send_keys() が行うこと

send_keys() は WebElement に定義されているため、driver.find_element(By.NAME, "q").send_keys("selenium") のように、必ず特定済みの要素に対して呼び出します。このメソッドは 1 つ以上の値を受け取ります。シグネチャは可変長引数の send_keys(*value) で、各値は入力する文字の文字列であり、渡された順に送信されます。特殊キー(Enter、Tab、Backspace、修飾キー)は selenium.webdriver.common.keys.Keys に定義されています。各定数は Unicode 私用領域の 1 文字にすぎないため、通常の文字列に混在させることも、element.send_keys("text", Keys.ENTER) のように別々の引数として渡すこともできます。element.send_keys("selenium" + Keys.ENTER) はテキストを入力してから Enter を押します。

実際の使用では 2 つの点が重要です。

  • send_keys() はタイピングをシミュレートします。入力を行うだけで、その後どうなるかはアプリケーション自身のロジックが決めます。ログインが拒否されるか、検索が実行されるか、フィールドにメッセージが表示されるかは、テストが観察するアプリケーションの動作であり、send_keys() が実行する処理ではありません。
  • 要素は入力を受け付けられる必要があります。テキストフィールド、テキストエリア、contenteditable 要素、ファイル入力(テキストとしてファイルパスを受け取ります)は機能しますが、単純な <div> にキーを送ってもイベントは届くものの、通常は何も変化しません。

ページをセットアップして要素を特定する

キーを送信する前に、ドライバーを起動し、ページを開き、対象の要素を見つけます。from selenium import webdriver と from selenium.webdriver.common.by import By を使った最小限のセットアップは、driver = webdriver.Chrome()、driver.get("https://www.google.com/")、そして search_box = driver.find_element(By.NAME, "q") です。現在の Selenium(バージョン 4)では driver.find_element(By.*, "...") で要素を特定します。以前の find_element_by_id、find_element_by_name などのメソッドは削除されました。

フィールドが動的にレンダリングされるページでは、推測に頼らず要素を待ちます。selenium.webdriver.support.ui の WebDriverWait と selenium.webdriver.support の expected_conditions as EC を使い、WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.NAME, "q"))) は要素の準備ができた時点でその要素を返します。特定の前に固定の time.sleep() を置く方法は脆く、要素のレンダリングが遅れればテストは失敗します。

利用できる中で最も安定したロケーターを優先します。まず要素 ID、次に name または CSS セレクター、構造ベースの検索には XPath を使います。本記事のブラウザーを使うスニペットは、pip install selenium とインストール済みのブラウザーを前提とし、ドライバーは Selenium Manager 経由で解決されます。これらは Selenium 4 向けに書かれており、ここで実行したものではなく、読者が適応させるためのインライン構文として示しています。

テキストとキーボードキーを送信する

フィールドに入力するには、テキストを send_keys() に渡します。フォームを送信するには Keys.ENTER を末尾に追加するか、2 回目の呼び出しで送信します(Keys は selenium.webdriver.common.keys にあります)。上で特定した Google のページでは、search_box.send_keys("This is filed by Selenium send keys") がクエリを入力し、search_box.send_keys(Keys.ENTER) がそれを送信します。send_keys() 内で送った修飾キー(たとえば Keys.CONTROL + "a")はキーを同時に押しますが、同じ修飾キーをもう一度送るか Keys.NULL を送って明示的に解放するまで、押されたままになります。Keys.chord(Keys.CONTROL, "a") はキーコンビネーションの後に Keys.NULL を追加するため、修飾キーが自動的に解放される形です。

スクリーンショットは、Google の検索フィールドに入力されたテキストを示しています。

Selenium send_keys() - 例 1

Keys 定数は 1 文字なので、自分で文字列を組み立てると、キーコンビネーションが何を追加するのかが正確にわかります。次の例を実行してください。なお、例のコード内のコメントと出力される値は英語のまま表示されます。

select_all = "\ue009" + "a"        # Keys.CONTROL + "a"
field_value = "selenium" + "\ue007"  # text + Keys.ENTER
print(len(select_all), len(field_value))
2 9

各 Keys 定数は 1 文字として数えられるため、"selenium" + Keys.ENTER は 9 個のキーイベントを送信します。8 文字の英字と Enter です。

入力を検証して結果を確認する

send_keys() 自体は何もチェックしません。検証を行うのはアプリケーションです。検証をテストするには、値を送信し、アプリケーションを動作させてから、表示された内容を読み取ります。ログインフォームでは email = driver.find_element(By.NAME, "email")、email.send_keys("not-an-email")、email.send_keys(Keys.ENTER) の順に実行し、その後 2 つの一般的な確認を行います。email.get_attribute("value") はフィールドの内容を読み戻します(テキスト入力は内容を要素の .text ではなく value に保持します)。driver.find_element(By.CSS_SELECTOR, ".error-message").text はアプリケーションがレンダリングする応答を読み取ります。

同じパターンで一般的なシナリオをカバーできます。メールアドレスのフィールドでは形式を崩す値を送ってアプリケーションが拒否することを確認し、パスワードフィールドでは各ルールを破る値を送って対応するメッセージを確認し、検索バーではクエリを送ってアプリケーションが返す結果が適切かを確認します。いずれの場合も send_keys() がキーストロークを供給し、アプリケーションの応答はアサーションで確認します。

テキストを消去または置き換える

フィールドを上書きする方法は 2 つあります。

  • element.clear() は 1 つの WebDriver コマンドで編集可能なフィールドを空にします。
  • キーボード操作による編集は、1 キーストロークずつテキストを削除または選択します。Keys.BACKSPACE はキャレットの前の文字を削除し、Keys.DELETE は後ろの文字を削除します。Keys.CONTROL + "a" は全体を選択するので、次の send_keys() 呼び出しで置き換えられます。

この区別は、フィールドがキーストロークごとに反応する場合に重要です。オートコンプリートやライブフォーマッターは実際のキーイベントを必要とすることがありますが、clear() は 1 回の更新を発行するだけです。Google の検索ボックスでの編集手順は、search_box.send_keys("For test purpose") で値を入力し、search_box.send_keys(3 * Keys.BACKSPACE) で末尾の 3 文字を削除し(“For test purp” が残ります)、search_box.clear() でフィールドを空にし、search_box.send_keys("testing second key") で新しいテキストを入力します。呼び出しの間に time.sleep(3) を挟むとブラウザーで各ステップを確認でき、終了時には driver.quit() でブラウザーを閉じます。

最初のステップ — テキストがフィールドに入力されます。

Selenium send_keys() - 例 2 の最初のステップ

2 番目のステップ — Backspace で 3 文字が削除され、“For test purp” が残ります。

Selenium send_keys() - 例 2 の 2 番目のステップ

3 番目のステップ — clear() でフィールドを空にし、新しいテキストを再入力します。

Selenium send_keys() - 例 2 の 3 番目のステップ

send_keys() のトラブルシューティング

入力が要素に届かない場合は、次のチェックを順に行います。

  • NoSuchElementException: ロケーターが一致しない、ページのレンダリングが終わっていない、または要素が <iframe> や shadow DOM の内部にある場合です。WebDriverWait で待機し、フレーム内のコンテンツには driver.switch_to.frame(...) を使います。
  • StaleElementReferenceException: 要素を特定した後にページが再レンダリングされた場合です。入力の直前に要素を再度特定します。
  • ElementNotInteractableException: 要素が非表示、無効、または覆われている場合です。要素を表示範囲までスクロールし、element_to_be_clickable を待ち、disabled 属性と readonly 属性を確認します。読み取り専用のフィールドは入力を拒否します。
  • InvalidElementStateException: 対象を編集できない場合です。たとえば編集不可の要素に対して clear() を呼び出したケースです。
  • 何も表示されない: フォーカスが別の場所にある可能性があります。先に要素をクリックするか、ActionChains(driver).move_to_element(el).click().send_keys(text) で操作します。element.get_attribute("value") を読み取り、届いた内容を確認します。
  • ショートカットと特殊キー: Keys 定数または Keys.chord() を使います。send_keys() は物理的なキーストロークではなく文字を送信するため、IME 変換が必要な文字体系では IME 合成を駆動しません。