PowerShell から Microsoft Edge WebDriver + Selenium を使った Web スクレイピングの方法を紹介します。WebDriver を使うとブラウザをプログラムから操作することができるようになります。環境は Windows11 の標準状態です。
1. はじめに
WebDriver というと、Chrome + Python 環境がメジャーで取り上げているサイトが多いのですが、Microsoft Edge + Power Shell 環境は情報が少ないです。注意点を交えながら紹介します。
Selenium は言語別にライブラリが用意されており、PowerShell が利用できるのは .NET 版です。.NET 版での想定言語は C# です。PowerShell は C# と文法が違うところがあるためサンプルはそのまま使用できないので、読み代える必要があります。そこが敷居が高く感じられる原因かもしれません。
WebDriver の利用シーンはサイトを解析しながら徐々に進めていくためC#のようなコンパイル言語は不向きで、インタプリタな PowerShell のほうが圧倒的に効率が良いです。人気の Python もインタプリタですしね。
PowerShellは使いこなせば凄いパワーを秘めています。ポイントはWindowsに標準で搭載されているので、自由にソフトをインストールできない会社でも使える点です。体系的に学びたい中級者はこちらがおすすめ。PowerShellの設計者が書いた本なので、設計思想から学べます。
2. 環境構築
2.1 Microsoft Edge WebDriver
マイクロソフトからEdge版の WebDriver をダウンロードします。Edgeのバージョンを確認して、同じバージョンのものをダウンロードしてください。
ファイル名は edgedriver_win64.zip です。
2.2 Selenium.WebDriver
C#向けのWebDriver はNuGet で公開されています。
www.nuget.org
NuGet の環境があればコマンドで入手できますが、無い場合はパッケージをダウンロードします。
ファイル名は selenium.webdriver.4.2.0.nupkg です。
2.3 フォルダに展開
まず作業ディレクトリを決めましょう。スクリプトはパス依存しないように構築するのでどこでも良いです。
作業ディレクトリに以下の2個のファイル(msedgedriver.exe、WebDriver.dll)を置きます。
(1). edgedriver_win64.zip の中から msedgedriver.exe
(2). selenium.webdriver.4.2.0.nupkg は zip 圧縮したファイルなので、拡張子を zip にすると展開ができます。lib\net48 の下の WebDriver.dll
これで下準備は完了です。
3 PowerShell
3.1 接続まで
最初の手続き部分を関数化します。
今回の記事では PowerShell のスクリプトと msedgedriver.exe、WebDriver.dllを同じディレクトリに配置することを想定しています。もちろん、特定のディレクトリ配置して絶対パスで指定して動かすこともできますので、カスタマイズしてください。
絶対パスの表記を避けるために最初にスクリプトのパスをカレントディレクトリに設定しています。
using namespace OpenQA.Selenium # スクリプトの位置をカレントディレクトリに設定 Set-Location $PSScriptRoot Function Create-EdgeDriver { $ret = [Reflection.Assembly]::LoadFile((Join-Path (Get-Location) "WebDriver.dll")) Write-Host $ret $opt = New-Object Edge.EdgeOptions # Edge へのフルパス $opt.BinaryLocation = "C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe" # msedgedriver.exe の絶対パスを登録 $svc = [Edge.EdgeDriverService]::CreateDefaultService((Get-Location)) $driver = New-Object Edge.EdgeDriver($svc, $opt) $driver.Manage().Timeouts().ImplicitWait = [System.TimeSpan]::FromSeconds(4) #暗黙的な待機4秒 return $driver } $driver = Create-EdgeDriver
PowerShell から WebDriver.dll を読み込み、EdgeDriver オブジェクト($driver)を生成しています。生成すると msedgedriver.exe と Edge 本体が起動されます。
ps1 --- WebDriver.dll --- msedgedriver.exe ---- Edge という接続が確立している状態です。
msedgedriver.exe は、プロキシーとして中間に位置しています。
うまく起動できない場合は、Edge のフルパスが合っているか確認して、違っていれば正しいパスに書き換えてください。
この後 $driver を使ってEdge を操作していきます。
3.1 WebDriver による散策
URLへの移動は以下です
# URLへ移動 $driver.Navigate().GoToUrl("ターゲットのURL")
要素の検索は注意が必要です。C#など他の言語だとByに括弧が不要ですっきりしています。
// C#でのコール例 x = driver.FindElement(By.ClassName("クラス名"))
PowerShell では以下の表記になります。
# クラス名で単一項目を取得 名前空間を含めたフルパス $x = $driver.FindElement( [OpenQA.Selenium.By]::ClassName("クラス名") )
型名称に括弧をつける言語仕様が醜くしています。
OpenQA.Selenium が名前空間
By がクラス名
ClassNamee が関数名
名前空間を using しておくことで、OpenQA.Selenium は省略できます。
# クラス名で単一項目を取得 名前空間を含めたフルパス $x = $driver.FindElement( [OpenQA.Selenium.By]::ClassName("クラス名") ) # using OpenQA.Selenium 使用時の名前空間省略形 $x = $driver.FindElement( [By]::ClassName("クラス名") ) # 空白を含むクラス名の場合は XPath で取得 $x = $driver.FindElement([By]::XPath('//div[@class="空白を含むクラス名"]')) # タグ名称で単一項目を取得 $x = $driver.FindElement([By]::TagName("タグ名")) #集合を取得する場合は複数形の FindElements をコールする $x = $driver.FindElements([By]::TagName("タグ名"))
詳細は公式サイトを参照ください。
https://www.selenium.dev/selenium/docs/api/dotnet/html/T_OpenQA_Selenium_Edge_EdgeDriver.htm
FindElementByClassName など [By]::~ の部分を関数名に展開した関数が記載されていますが、実際に使えるのは上記の単数形のFindElement() と複数形の FindElements() だけでした。
定型パターンを紹介します
リストの各行を取得する
連続する集合を取得するケースです。以下のリストを想定すると、まずクラスでリストの1つ上の階層をひっかけます。そのあと、FindElements()で リスト部分を集合として取得します。ここまでくると、PowerShell の定石に持ち込めます。
<div class="AAA"> <li> </li> <li> </li> <li> </li> </div>
$x = $driver.FindElement([By]::ClassName("AAA")) $x.FindElements([By]::TagName('li')) | % { # あとは $_ を使ってリストの各要素にアクセス }
最後に
PowerShell でも WebDriver を自由に使えるようになりました。一度やり方がわかればそれほど難しくはありません。
次回は実用偏として、WebDriver で抽出した画像を Excel に自動貼り付けする方法を紹介します。