Selenium×Pythonで”input type=”file”がボタンクリック後にしか出現しない場合の対処法

備忘録

はじめに

SeleniumとPythonで自動テストを行っていると、ファイルアップロード処理が壁になることがある。
特に、<input type="file">要素が初期状態では非表示で、ユーザーが「アップロード」ボタンをクリックした後にのみDOM上へ生成されるケースだ。

このタイプのサイトでは、SeleniumがボタンをクリックするとWindowsのファイルエクスプローラーが開くが、Selenium自体はそのネイティブダイアログを制御できない。
そのため自動化の流れが中断してしまう。

この記事では、ファイルエクスプローラーを強制終了することで<input type="file">を操作可能にする回避策を紹介しつつ、そのリスクと代替案を整理する。


スポンサーリンク
スポンサーリンク

手順:ファイルエクスプローラー強制終了による回避策

1. 通常のボタン操作を行う

まず、対象の「ファイルをアップロード」ボタンをクリックする。
この操作によってファイルエクスプローラーが起動する。

upload_button = driver.find_element(By.ID, "upload")
upload_button.click()

2. ファイルエクスプローラーをプロセスレベルで終了

ファイルエクスプローラーが開いた直後に、そのプロセスを終了させる。
すると<input type="file">がDOM上に残り、Seleniumのsend_keys()でパス指定が可能になる。

import os
import signal
import subprocess

# explorer.exeのプロセスを強制終了
subprocess.run(["taskkill", "/im", "explorer.exe", "/f"])

その後、通常通りファイルパスを送信できる。

file_input = driver.find_element(By.CSS_SELECTOR, "input[type='file']")
file_input.send_keys("C:\\path\\to\\file.txt")

この手法は単一のブラウザインスタンスでは機能するが、複数ブラウザ(例:Braveを15ウィンドウ同時起動など)ではリスクが高い。
タスクマネージャー上では同名のプロセスが並び、間違って別のブラウザやシステムプロセスを終了させる可能性がある。


注意点と代替案

この「プロセス強制終了」アプローチは、あくまで裏技的な回避策だ。安全性の観点からは、以下の方法を検討したい。

DOM操作による擬似的レンダリング

実装によっては、クリックによってファイルエクスプローラーを開かずとも、JavaScript経由で<input type="file">を直接レンダリングできることがある。
たとえば開発者ツールで要素の生成を確認し、同じ構造をSeleniumから強制的に作成する方法だ。

driver.execute_script("""
    let input = document.createElement('input');
    input.type = 'file';
    document.body.appendChild(input);
""")

OS操作をキャンセルする

もう一つの方法として、Robotクラスpyautoguiを使い、開いたファイルエクスプローラーを「Esc」キーでキャンセルする手法もある。
これにより、強制終了よりも安全にエクスプローラーを閉じることができる。

import pyautogui
pyautogui.press('esc')

この後、ページ上に残った<input type="file">をSeleniumで操作すれば良い。


まとめ

ファイルアップロードの自動化は、Seleniumにおける典型的な難関の一つだ。
<input type="file">が動的に生成される場合、ファイルエクスプローラーの制御不能問題が発生しやすい。
強制終了による回避は一時的な解決にはなるが、プロセス識別が難しく、システムの安定性を損なう危険もある。

最も安全なのは、DOMを直接操作する方法か、ネイティブダイアログを開かない構造を開発側に依頼することだ。
もしテスト自動化を維持する必要があるなら、上記のようなスクリプト操作で代替するのが現実的だ。

コメント