Webブラウザの操作を自動化で行いたい処理の一つに、ファイルのアップロードがある。いちいちファイル選択ダイアログで選ぶのは面倒だからだ。そしてこの処理は自動化に失敗しやすい部分でもある。今回は、アップロードの自動化について取り上げる。
→連載「PowerShell Core入門 - 基本コマンドの使い方」の過去回はこちらを参照。
ファイル選択に使うサンプルページ
今回も前回と同じ「https://getbootstrap.jp/docs/5.0/examples/cheatsheet/」をサンプルページとして使用する。
このページの上から3分の1くらいのところにファイル選択のボタン(input要素)が用意されているので、これを使う。例のごとく、要素を操作するにはXPathが必要になるので、Microsoft Edgeの開発者モードで対象となる要素のXPathを調べておく。
要素 | XPath |
---|---|
ファイル選択 | //∗[@id="customFile"] |
その下のスイッチ | //∗[@id="flexSwitchCheckChecked"] |
なお、操作上使うことになるので、ファイル選択ボタンの下にあるスイッチボタンのXPathも調べて上の表に加えてある。
PowerShellから操作していく
では早速、PowerShellから操作していく。まず、WebDriverおよびMicrosoft Edgeを起動し、さらにhttps://getbootstrap.jp/docs/5.0/examples/cheatsheet/をオープンする。「webdriver_edge_start.ps1」は稿末に付録として掲載してあるので参考にしていただきたい。
webdriver_edge_start.ps1
Set-SeUrl -Url https://getbootstrap.jp/docs/5.0/examples/cheatsheet/
これでhttps://getbootstrap.jp/docs/5.0/examples/cheatsheet/が開くので、とりあえず手動で3分の1ほどスクロールし、ターゲットとなるファイル選択ボタンを表示させておく。
XPathを指定して対象となるファイル選択用のinput要素を取得する。
$Element = Get-SeElement -By XPath -Value '//*[@id="customFile"]'
ファイルの選択は、Invoke-SeKeysコマンドレットでファイルパスを送ることで実行できる。ここでは「~\Desktop\images.zip」というファイルを選択することにして、次のようにファイルパスを送る。
Invoke-SeKeys -Element $Element -Keys $env:HOME+"\Desktop\images.zip"
本来、これでファイルパスが設定されるのだが、Microsoft Edgeでは次のようにファイル選択用のダイアログが起動してくる。パスは全く関係ない状態になっている。
Google ChromeなどほかのWebブラウザだと先ほどの処理でファイルパスが設定されるのだが、Microsoft Edgeだとそうならない。実装を追っていないので確かなことはわからないが、セキュリティポリシーでこの処理を禁止しているように思われる。自動的にファイルをアップロードされるというのはセキュリティ上は好ましくないということから、禁止しているのかもしれない。
しかし、これでは困る。自動化したい。
ファイル選択のダイアログはOSの管轄になるので、Selenium (WebDriver)経由では操作できない。このままでは、せっかくほかの処理を自動化してもファイルの選択だけは手動で行うことになる。それでは中途半端というものだ。
OSの管轄なのであれば、OSの提供する機能を使ってファイル選択ダイアログの操作を自動化すればよい。幸い、PowerShellは.NETの機能にアクセスできるので、OSが管轄する機能に関しても結構いろいろなことができる。この辺り、PowerShellはWindowsとの相性が良い。PowerShellが提供していない機能でも、いざとなったら.NETやWindows APIの機能を引っ張ってきて使ってしまえばよいので、やろうと思えばかなりのことができるのだ。
今回はSystem.Windows.Forms経由でウインドウにキー入力を送り込めば解決する。そこで、この機能を使うためにadd-typeを実行する。
add-type -AssemblyName System.Windows.Forms
そして、先ほどと同じようにしてファイル選択ダイアログを起動し、確実にファイル選択ダイアログが起動してフォーカスがそこに移動するまで処理待ちを行う。
Invoke-SeKeys -Element $Element -Keys $env:HOME
sleep 0.5
ここまで準備したら.NETの機能を使ってファイルパスの入力と選択処理を行う。
[System.Windows.Forms.SendKeys]::SendWait("C:\Users\daichi\Desktop\images.zip`n")
これでアクティブになっているウインドウに「C:\Users\daichi\Desktop\images.zip改行」というデータが送信される。実際には、ファイル選択ダイアログの「ファイル名」のところにファイルパスが入力されていく様子を見ることができる。
最後に改行が入っているので、改行が押された状態になる。つまり「開く」ボタンが押されたことになって、ファイル選択ダイアログは終了する。
そしてMicrosoft Edgeに表示されていたファイル選択要素のところに、選択したファイルが表示されることを確認できる。
Seleniumの機能だけではなく.NETの機能も使っているが、実はファイル選択の処理はSeleniumだけだと処理できないケースがあり、その場合にはここで取り上げたようにOSの機能を使って自動操作を続けることになる。このやり方は覚えておいて損はない。