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 の検索フィールドに入力されたテキストを示しています。
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() でブラウザーを閉じます。
最初のステップ — テキストがフィールドに入力されます。
2 番目のステップ — Backspace で 3 文字が削除され、“For test purp” が残ります。
3 番目のステップ — clear() でフィールドを空にし、新しいテキストを再入力します。
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 合成を駆動しません。