この記事は、ZOZO #11 Advent Calendar 2024 6日目の記事になります。
昨日は@ssssotaさんの記事でした。
はじめに
コーポレートエンジニアでは省力化のため自動化をおこなっています。
ランサムウェアの被害が多発している昨今、セキュリティ対策がますます重要になっています。
Windows共有禁止や、リモートワーク環境で認証レスでのファイル置き場に制限など。
運用スクリプトでファイルを取得するにもセキュリティ意識が必要な時代です。
そこで今回はPowerShellでEdgeの自動操縦について紹介します。
おさらい
- 昔はInvoke-RestMethodでファイルをダウンロードすることが出来ました。
# ユーザー名とパスワードを設定
$username = "yourUsername"
$password = "yourPassword"
# 認証情報を作成
$securePassword = ConvertTo-SecureString $password -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential($username, $securePassword)
# Restメソッドでファイルをダウンロード
Invoke-RestMethod -Uri $downloadUrl -Method Get -Credential $credential -OutFile $downloadPath
しかし最近の動的なWebサイトでは、この方法ではダウンロードが出来ないことが増えてきました。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>動的なWebページ</title>
<script>
document.addEventListener("DOMContentLoaded", function() {
// 動的に生成する内容
var content = `
<h1>ようこそ</h1>
<p>これは動的に生成されたコンテンツです。</p>
<button id="downloadButton">ファイルをダウンロード</button>
`;
// bodyにコンテンツを追加
document.body.innerHTML = content;
// ダウンロードボタンにイベントリスナーを追加
document.getElementById("downloadButton").addEventListener("click", function() {
// ダウンロード処理
window.location.href = "path/to/your/file.zip";
});
});
</script>
</head>
<body>
<!-- 初期のbodyは空 -->
</body>
</html>
動的にページを生成するアプリでファイルのURLの都度変更やUIのHTMLの動的生成が行われている場合もあり固定のダウンロードURLではファイルが取得できません。
そこで、Edgeの自動操縦となります。
Edgeの自動操縦
前提
- 今回のスクリプトはWindowsServerに入っている 5.1系のPowerShellを想定
- Edgeのバージョンも比較的最新のものを想定
WebDriverの紹介
WebDriverは、ブラウザを自動操作するためのプロトコルです。
過去のTrident エンジンベースのEdge Legacyであれば設定>オプション機能から有効にすることが出来ましたが、現在のBlinkエンジンのEdgeでは準備が必要となります。
Edgeのバージョン確認
構築スクリプトを作りこみたい場合もあるかと思いますのでスクリプトでのEdgeのバージョンの確認について紹介します。
$edgeVersion = (Get-Item (${env:ProgramFiles(x86)} + "\Microsoft\Edge\Application\msedge.exe")).VersionInfo.FileVersion
# 131.0.2903.63
WebDriverのダウンロード
Microsoft Edge Developer で調べたEdgeバージョンとアーキテクチャが一致しているWebDriverを選んでダウンロードします。
完全一致のものが見つからない場合はEdgeバージョンのドットの右側から削って一致するものを選びます。
Selenium モジュールダウンロード
NuGetからSeleniumモジュールをダウンロードします。
-
NuGet Gallary|Selenium.WebDriver 4.26.1
- Download package (12.55 MB) のリンクをダウンロードして拡張子をzipに変更して展開して利用します。
ファイルの展開
- Selenium.WebDriver をzip展開
- 同じフォルダに msedgedriver.exe を配置
プロジェクトルート/
├── webdriver/
│ ├── _rels/
│ ├── build/
│ ├── Driver_Notes/
│ ├── images/
│ ├── manager/
│ ├── package/
│ ├── .signature.p7s
│ ├── [Content_Types].xml
│ ├── msedgedriver.exe
│ ├── Selenium.WebDriver.nuspec
├── src/
│ ├── Get-EdgeWebDriver.ps1
│ └── Script.ps1
└── run.bat
スクリプト
run.bat
- ファイルの位置をカレントディレクトリに設定してからスクリプトを実行
- 複数のファイルなのでカレントディレクトリを設定してから実行することでファイルの位置を意識しなくても実行できる
@echo off
pushd %~dp0
powershell -File .\src\Script.ps1
Get-EdgeWebDriver.ps1
- EdgeWebDriver の環境構築
- オブジェクト生成は.NETのクラスを利用して行う
using namespace OpenQA.Selenium
# 設定ファイル読み込み
Function Get-EdgeDriver{
<#
.SYNOPSIS
EdgeWebDriver の環境構築
.DESCRIPTION
msedgedriver.exe と net48 の WebDriver.dll を利用して EdgeDriverを作成する
#>
# スクリプトの位置をカレントディレクトリに設定
$basePath = Get-Item -Path (Join-Path (Get-Location) ./webdriver).FullName
$ret = [Reflection.Assembly]::LoadFile((Join-Path $basePath "lib\net48\WebDriver.dll"))
$opt = New-Object Edge.EdgeOptions
# Edge へのフルパス
$opt.BinaryLocation = "${env:ProgramFiles(x86)}\Microsoft\Edge\Application\msedge.exe"
# msedgedriver.exe の絶対パスを登録
$svc = [Edge.EdgeDriverService]::CreateDefaultService($basePath)
$driver = New-Object Edge.EdgeDriver($svc, $opt)
$driver.Manage().Timeouts().ImplicitWait = [System.TimeSpan]::FromSeconds(4)
# 暗黙的な待機4秒
return $driver
}
Script.ps1
- メインスクリプト
- EdgeDriverを利用してWebページを操作するスクリプト
using namespace OpenQA.Selenium
. ./Get-EdgeWebDriver.ps1
# EdgeDriver起動
$driver = Get-EdgeDriver
# URLへ移動
$driver.Navigate().GoToUrl("https://path/to/your/url")
# ログインページ
$username = $driver.FindElement([By]::XPath('//input[@id="id"]'))
$username.SendKeys("yourUsername")
$password = $driver.FindElement([By]::XPath('//input[@id="password"]'))
$password.SendKeys("yourPassword")
$login = $driver.FindElement([By]::XPath('//input[@id="loginButton"]'))
$login.Click()
# メニューページ
$menu = $driver.FindElement([By]::XPath('//div[@class="menu_elements"]/a'))
$menu.Click()
# ダウンロードページ
$download = $driver.FindElement([By]::XPath('//input[@id="download"]'))
$download.Click()
# ダウンロード待ち
Start-Sleep -Seconds 10
# EdgeDrive終了
$driver.Quit()
# Downloadフォルダから最新CSVファイルをスクリプトのローカルに移動
$downloadFile = ( Get-ChildItem -Path "$env:USERPROFILE\Downloads" -Filter "*.csv" | Sort-Object CreationTime -Descending)[0]
Move-Item -Path $downloadFile.FullName -Destination (Join-Path (Get-Location) "GetCSVFile.csv") -Force
- "https://path/to/your/url" へ接続
- ログインページが完成するのを暗幕の待機で待つ
- ユーザー名入力欄をDOMのXPathから取得
- ユーザ名をSendKeysで入力
- パスワード入力欄をDOMのXPathから取得
- パスワードをSendKeysで入力
- ログインボタンをDOMのXPathから取得
- ログインボタンをクリック
- メニューページが完成するのを暗幕の待機で待つ
- メニューページのリンクをDOMのXPathから取得
- メニューページのリンクをクリック
- ダウンロードページが完成するのを暗幕の待機で待つ
- ダウンロードリンクをDOMのXPathから取得
- ダウンロードリンクをクリック
- ダウンロード完了まで10秒待つ
- EdgeDriverを終了
- ダウンロードフォルダから最新のCSVファイルをスクリプトのローカルに移動
- Xpathの調査や評価については目的のサイトをEdgeで開いてF12で開発者ツールを開いて該当の要素を選択して右クリックからCopy>Xpathで取得できます
まとめ
- Edgeの自動操縦について紹介しました
- PowerShell 5.1系で実行出来るためWindowsServerにインストールは最小限で済みます
- PowerShellスクリプトを自己証明書で署名する運用にするとセキュリティも向上します
明日も私(@zz_takumi_ito)で「Google スプレットシートで簡易検索について」になります。
お楽しみに。