send_keys()を使わない理由
アップロードに苦戦して私もいろいろ試していましたが、調べているとよく当たるのがsend_keys()でファイルパスを打ち込めばアップロードできるよ!という手法。どこのサイトでも同じような方法で紹介されていて、実際にダイアログを回避しつつアップロードできるサイトもあります。しかしながら、Seleniumを使った自動化に都合よく対応しているサイトばかりではなく、中にはsend_keys()ではうんともすんとも言わずにアップロードできないようなサイトもあります。
使わない理由というのも正しくなく、Seleniumではファイルダイアログの操作はできません。便利な手法を使うにも使えなかったから消去法的に他の方法で試すしかなかったというのが正しい理由になります。冒頭にあげた環境でかつsend_keys()が使えないようなサイトでアップロードの作業をしたい方に向けて詳細を記載していきます。この手法を使えるようになると、ファイルダイアログや印刷のダイアログなど、WindowsOSが絡むようなダイアログの操作をSeleniumの処理の途中に挟み込みつつ、テストを自動化することに応用できるでしょう。
アップロードをするコード
pywinauto
import pywinauto
def upload_file(file_fath):
# 開くダイアログを探して接続する
findWindow = lambda: pywinauto.findwindows.find_windows(title=u'開く')[0]
dialog = pywinauto.timings.wait_until_passes(5, 1, findWindow)
pwa_app = pywinauto.Application()
pwa_app.connect(handle=dialog)
window = pwa_app[u"開く"]
# テキストボックス(ファイル名)にPATHを入力
tb = window[u"ファイル名(&N):"]
if tb.is_enabled():
tb.click()
edit = window.Edit4
edit.set_focus()
edit.set_text(file_fath)
# 開くボタンを押す(Alt+O)
pywinauto.keyboard.send_keys("%O")
ahk
(2021-02-06追加)
def upload_file(file_path: str) -> None:
"""
ファイルアップロードのダイアログを動かしてアップロードするファイルを設定する
:param file_path: Str
:return: None
"""
ahk = AHK()
time.sleep(1)
ahk.send_input(file_path)
ahk.key_press("Enter")
pywinautoのコメント
アップロードとは関係ないかもしれませんが、下のURLのサイトを参考にしました。Windowsのダイアログ等の操作をする上でとても参考になりました。https://ohtorii.hatenadiary.jp/entry/20171029/p1
「pip install pywinauto pywin32」で上のコードの動作に必要なライブラリを入手してください。あわせて、自身の環境にあうバージョンのpywin32を下のURLから探してインストールしてください。 https://sourceforge.net/projects/pywin32/files/pywin32/
Seleniumと同じような感覚で、ドライバのようなもの(ウィンドウ)を探し出して取得して、その中の要素をクリックしたり、キーを送信したりして操作をします。
findWindow = lambda: pywinauto.findwindows.find_windows(title=u'開く')[0]ではタイトルを手がかりにしてウィンドウを探し出します。pywinauto.timings.wait_untilでは、上の探し出す処理が完了してTrueになるか、trueにならずにタイムアウトするかどちらかの状態になるまで処理を待ちます。pywinauto.timings.wait_until(タイムアウトまでの時間, 繰り返す間隔(Sec), 組み込み関数)の書式になっています。詳細はURLより。https://pywinauto.readthedocs.io/en/latest/code/pywinauto.timings.html
pwa_appの処理では見つけ出したウィンドウをpywinautoに接続します。接続するとpywinautoを使ってダイアログ上にある要素を操作できるようになります。最後に"ファイル名(&N):"をクリックしてファイルパスを入力、最後にショートカットキーを送ってファイルの選択が完了します。
冒頭のサンプルコードはGoogleアカウントとGoogleフォームを使ってファイルのアップロードのダイアログを操作するものです。IDとパスワードをご自身のものに変えて、ローカルファイルのパスを入力するとフォーム上でアップロードの自動化テストができます。
ただ、本当に動作してしまうと私のドライブにファイルが送られるので、ファイルを読み取ったのを確認できたらアップロードをキャンセルして、かつアップロードされるファイルがないのでフォームの送信ができない状態で終わります。コメントアウトで「# キャンセルボタンを押す」とした箇所を書き換えてアップロード処理をしたら完動品としてつかえるものです。ご自身の環境にあわせて書き換えて実際のアップロードの操作をしていただけたらとても嬉しいです。
今回はアップロードのコードがメインのため、サンプルコードの他の箇所の解説は割愛します。
追記(2020/06/06)
そのほかの手法としてはアップロードダイアログがアクティブになった際にahk(auto hot key)でウィンドウを取得してアップロードのファイルパスをsend_keyしてアップロードすると短くコードを書くことができます。詳細はPyPIにてご確認ください。
AutoHotKey
(2020-02-06追記)
AutoHotKeyでもpywinautoと同様にファイルダイアログを使ってアップロードできます。pywinautoのようにPythonのバージョンと合わせてexeファイルを取得する必要もなく、一度AutoHotKeyをインストールすると長く使える環境をつくれます。また、Pythonのコードも短く済む傾向にありオススメです。
send_key()でアップロードできない時にはぜひこちらをご活用ください。
DL