1.経緯について
RPAのソフトをインストールできないので、これまでVBSでCreateObjectでブラウザの自動操作をすることがたまにあった。
※いざというときの手札として持っているだけで安心感が段違い
見た目上IEがインストールされていなくても、CreateObjectをしたときにIEを呼び出すことができている状態ではあるが、Edgeでないと動かないようなシステムが出てきた場合のためにWebDriverなどのソフトをインストールせずにPowerShellといくつかのファイルをダウンロードするだけで自動化できる手段を探したところ、qiita.comにいくつか紹介がされているものがあった。
試してみたところエラーに次ぐエラーですぐに試すことができなかったので備忘録として記録をしておく。
サンプルとして郵便追跡サービスを自動操作しCSVをダウンロードするソースコードを載せてありますが、あくまで検証用です。サーバーに負荷をかけるような処理はしないでください。
※なお今時であればMicrosoftで無料のPowerautomateがあるので、それを使えばもっと安定かつノーコードで行けるのでいいと思いますが・・・。
2.はまったところ
・はまったポイント1
ダウンロードしたdllを「LoadFile("WebDriver.dll")」で読み込んだらエラーが発生。
エラーメッセージの一部:"ネットワーク上の場所からアセンブリを読み込もうとしました。これにより~~"
dllを右クリックしてプロパティを修正することで回避する
・はまったポイント2
「Newtonsoft.Jsonの依存関係がどうとか」いうエラーが発生し、「EdgeDriver」のインスタンス化でエラーが発生。
色々調べたところWebDriver.dllをダウンロードしたときに最新のものを取ってきすぎてバージョンが対応していなかった。
https://www.nuget.org/packages/Selenium.WebDriver/
最新のdllをダウンロードすればいいと安直に思って、4.22.0を「Download pakage」を押下し、ダウンロードして、「selenium.webdriver.4.22.0.nupkg」の拡張子「nupkg」を「zip」に変更し、「lib\netstandard2.0\WebDriver.dll」を取り出して、使おうとしていた。
→ サイトが表示されたら過去のものを手に入れるため「Full status」をクリックする。
「4.21.0」から順に開いていったが欲しいフレームワークのものがなかったので、「Show more」をクリックする
ひたすら順番に見ていくと、「4.12.3」でほしいフレームワークのものがあった。
・はまったポイント3
要素が表示されるまでの待機を入れるために「WaitDriverWait」(WebDriverSupport.dll)を入れて、「ExpectedConditions」クラスを指定しようとしたら全然できなかった。
→ いろいろと調べていくともう廃止されている。「$edgeDriver.Manage().Timeouts().ImplicitWait = (New-TimeSpan -Seconds 10)」とすることで要素が取得するまで待ってくれる、らしい。
3.最終的な手順
1)自分の環境に応じたバージョンのWebDriver.dllをダウンロードする
https://www.nuget.org/packages/Selenium.WebDriver/
※自分の環境で作業した時点だと「4.12.3」の「lib\net48\WebDriver.dll」で動いた。人によっては環境が異なるので、頑張って試していただければと思います。
2)ダウンロードしたWebDriver.dllを右クリック→プロパティを表示し、上述の「セキュリティ」を「許可する」に設定する
3)EdgeのWebDriver(msedgedriver.exe)をダウンロードする
https://developer.microsoft.com/ja-jp/microsoft-edge/tools/webdriver/?form=MA13LH&ch=1
5)Main.ps1に下記のソースを貼り付ける
例)郵便の追跡番号を自動で設定しCSVファイルをダウンロードする
# --------------- Parameter Start
# ◆ ファイルのダウンロードを待機する設定値
$INT_MAX_LOOP_COUNT_FOR_RETRY_DOWNLOAD_CHECK = 60; # 最大60回まで繰り返す
$INT_SLEEP_SECONDS_FOR_RETRY_DOWNLOAD_CHECK = 1; # リトライするまでの待機時間
# ファイルのダウンロードが終わっているかどうかをチェックする際の待機時間と最大チェック回数。
# 待機時間×最大チェック回数の時間以内にダウンロードが終わらないと処理がエラーで終了する
$STR_DOWNLOAD_DIRECTORY = "C:\Users\ユーザー名\Downloads\DriverFolder";
# --------------- Parameter End ファイルのダウンロードを待機する設定値
# dllのロード
$strCurrentDir = Split-Path $MyInvocation.MyCommand.path;
$webDriverDllPath = $strCurrentDir + "\WebDriver.dll";
$edgeDriverDirPath = $strCurrentDir + "\";
$asm = [System.Reflection.Assembly]::LoadFile($webDriverDllPath)
# ダウンロードフォルダが存在しない場合はフォルダを作成する
If(!(test-path $STR_DOWNLOAD_DIRECTORY)) { New-Item -ItemType Directory -Force -Path $STR_DOWNLOAD_DIRECTORY; }
# ◆ Edgeのオプションを生成
$Options = New-Object OpenQA.Selenium.Edge.EdgeOptions
## ダウンロードフォルダを指定し、ダウンロードプロンプトが表示されないようにする。
## https://stackoverflow.com/questions/35446893/c-sharp-set-default-download-directory-chrome-webdriver
$Options.AddUserProfilePreference("download.default_directory", $STR_DOWNLOAD_DIRECTORY);
$Options.AddUserProfilePreference("download.prompt_for_download", $false);
$Options.AddUserProfilePreference("disable-popup-blocking", "true");
## 拡張機能の自動更新を停止
$Options.AddArgument("useAutomationExtention=false")
## 「Edgeは自動テストソフトウェアによって制御されています」を非表示にする
$Options.AddExcludedArgument("enable-automation")
## ウィンドウサイズを最大にする
$Options.AddArgument("--start-maximized")
## EdgeDriverを生成する
$edgeDriver = New-Object OpenQA.Selenium.Edge.EdgeDriver($edgeDriverDirPath , $Options)
## Manage().Timeouts().ImplicitWaitを一度設定しておけば以降の
## FindElementやFindElementsで要素を取得するときに、毎回待機が行われるようになります。
## この処理が追加されたためWebDriverWaitを呼び出すときのExpectedConditionsクラスが廃止されている
$edgeDriver.Manage().Timeouts().ImplicitWait = (New-TimeSpan -Seconds 10)
# ◆ 郵便番号検索画面を操作する
## 郵便番号個別検索のケース
#$edgeDriver.Url = "https://trackings.post.japanpost.jp/services/srv/search/input"
#$x = $edgeDriver.FindElement([OpenQA.Selenium.By]::Name("requestNo1"))
#$x.SendKeys("123456789012")
## クリック
#$x = $edgeDriver.FindElement([OpenQA.Selenium.By]::Name("search"))
#$x.Click();
## 郵便番号連続のケース(最大100件ずつ検索ができる)
$edgeDriver.Url = "https://trackings.post.japanpost.jp/services/srv/sequenceNoSearch/input"
$x = $edgeDriver.FindElement([OpenQA.Selenium.By]::Name("requestNo"))
$x.SendKeys("123456789012") ## 調べたい番号の開始
$x = $edgeDriver.FindElement([OpenQA.Selenium.By]::Name("count"))
$x.SendKeys("1")
$x = $edgeDriver.FindElement([OpenQA.Selenium.By]::Name("sequenceNoSearch"))
$x.Click();
## Edgeの開発者ツールでCSVダウンロードボタンを見たところ、ダウンロード用のサブウィンドウを呼び出すJavaScriptを実行していることがわかったため、JavaScriptを呼び出す
$edgeDriver.ExecuteScript("openSubWindowForPost('openSequenceNoSearchCsvCreate', 'sequenceNoSearchCsv', 540, 380)");
# ◆ CSVダウンロード画面を操作する
## CSVをダウンロードするためのサブ画面が呼び出されるのでWebDriverで操作する画面を切り替える必要がある
$CurrentWindowHandle = $edgeDriver.CurrentWindowHandle; # 現在のウィンドウハンドルの番号を退避
$WindowHandles = $edgeDriver.WindowHandles; # WebDriverが操作できるすべてのウィンドウハンドルを取得する
## ダウンロード前のファイル名を退避
$arrFileitemsBefore = Get-ChildItem $STR_DOWNLOAD_DIRECTORY -File
$intFileCount = 0;
if( $arrFileitemsBefore -eq $null){ $intFileCount = 0;}
elseif ( $arrFileitemsBefore -is [array]){ $intFileCount = $arrFileitemsBefore.Length; }
else { $intFileCount = 1; }
## ダウンロード画面にDriverの操作画面を切り替えて、ダウンロードボタンを押下する
foreach ($handle in $WindowHandles){
if ($edgeDriver.SwitchTo().Window($handle).Title -like "*CSVダウンロード*"){
# ダウンロードボタンが取得できるまで繰り返すようにする
# このサイトの場合は、「CSVファイル作成を完了しました。」という文字が取れるまで待機してもよい課と思われる
$x = $edgeDriver.FindElement([OpenQA.Selenium.By]::Id("download"))
$x.Click();
break;
}
}
## 現在のファイル名を取得して比較して、存在しないファイル名があればダウンロードしたファイルと判断する
$strNewFileName = "";
$intLoopCount = 1 ;
$blnCompleteDonload = $false;
# ダウンロードが完了するまで待機する
# EdgeやChromeの場合、ダウンロード中かどうかは拡張子が「.crdownload」というファイルが作成されるので拡張子が変わるまで待機する
# ただしタイムアウトとして最大待ち時間は設定する
do {
# ダウンロード処理・待機時間後のファイル名を退避
$arrFileitemsAfter = Get-ChildItem $STR_DOWNLOAD_DIRECTORY -File
foreach($item in $arrFileitemsAfter){
$result = $arrFileitemsBefore | Where-Object Name -eq $item.Name ;
if($result -eq $null){
$strNewFileName = $item.Name;
if ($item.Extension -ne ".crdownload") {
$blnCompleteDonload = $true;
Write-Host("ダウンロード完了。ファイル名:" + $item.Name)
}
break;
}
}
$intLoopCount += 1;
if( $blnCompleteDonload -eq $true ){ break; }
else{ Start-Sleep -Seconds $INT_SLEEP_SECONDS_FOR_RETRY_DOWNLOAD_CHECK; }
} while ($intLoopCount -le $INT_MAX_LOOP_COUNT_FOR_RETRY_DOWNLOAD_CHECK)
# ダウンロードが終了したため、オブジェクトの終了をする
$edgeDriver.quit();
Exit;
0 件のコメント:
コメントを投稿