前回までに紹介した機能で、PowerShell Seleniumを経由したMicrosoft Edgeの操作はほぼできるようになったはずだ。これだけで、人が行っていた操作のほとんどをPowerShellから実行できるようになっている。今回は、機能としては最後のひと押しとなる「JavaScriptの実行」について取り上げる。

→連載「PowerShell Core入門 - 基本コマンドの使い方」の過去回はこちらを参照。

JavaScriptが実行できれば実質的に何でもできる

前回までに紹介した機能は、PowerShell Seleniumを使うことで、PowerShellのコマンドレットからMicrosoft Edgeの制御を行えるというものだった。これだけでもかなりのWebページの操作を自動化できる。

それでは提供されていない機能についてはどうか。その場合、PowerShell Seleniumを使って任意のJavaScriptコードを実行することができる。つまり、Webブラウザの開発者ツールを使って自由にページを操作できるのと同じことが、PowerShellからも実行できるわけだ。

サンプルページをJavaScriptで書き換えていく

今回は「https://getbootstrap.com/docs/4.0/examples/sign-in/」をサンプルページとして利用する。このページを表示した後、JavaScriptを実行してサンプルページの内容を書き換えるといった操作を行う。

  • https://getbootstrap.com/docs/4.0/examples/sign-in/

    https://getbootstrap.com/docs/4.0/examples/sign-in/

サンプルページを開発者ツールで調べておく。

  • 開発者ツールでWebページを調査

    開発者ツールでWebページを調査

Webページのコンテンツはbody要素がトップに位置していることが多い。body要素のXPathは「/html/body」だ。今回はこのbody要素を編集することにする。body要素は通常、Webページごとに1つしかないので、body要素を名前で取得するJavaScriptのコードを使っても十分なので、今回はその方法で実装する。

PowerShell SeleniumからJavaScriptを実行

早速PowerShell SeleniumからJavaScriptを実行してみよう。まず、Microsoft Edge WebDriverとMicrosoft Edgeの起動を行う。

PS C:\Users\daichi> webdriver_edge_start.ps1
Microsoft Edge WebDriverを起動します。
Microsoft Edge WebDriverの起動処理完了。
PS C:\Users\daichi> S
  • Microsoft Edge WebDriver制御下のMicrosoft Edge

    Microsoft Edge WebDriver制御下のMicrosoft Edge

webdriver_edge_start.ps1は付録として稿末に記すので、そちらを参照していただければと思う。

続いて、Set-SeUrlコマンドレットでサンプルページをオープンする。

PS C:\Users\daichi> Set-SeUrl -Url https://getbootstrap.com/docs/4.0/examples/sign-in/
PS C:\Users\daichi>
  • サンプルページがオープンされた状態

    サンプルページがオープンされた状態

PowerShell SeleniumからはInvoke-SeJavascriptコマンドレットを使うことでJavaScriptコードの実行を行える。ここでは次のようにInvoke-SeJavascriptコマンドレットを実行して、body要素に「style="background:black"」という属性を追加する処理を実行する。

PS C:\Users\daichi> Invoke-SeJavascript -Script '
>> e = document.getElementsByTagName("body");
>> e[0].setAttribute("style", "background:black");
>> '
PS C:\Users\daichi>

上記のようにInvoke-SeJavascriptコマンドレットを実行すると、サンプルページの表示が次のように変化する。JavaScriptコードを実行してbody要素に属性データを追加した結果が反映されていることがわかる。

  • Invoke-SeJavascriptコマンドレット実行後の表示

    Invoke-SeJavascriptコマンドレット実行後の表示

動作確認が終わったらMicrosoft Edge WebDriverとMicrosoft Edgeを終了する。

PS C:\Users\daichi> webdriver_edge_stop.ps1
動作しているMicrosoft Edge WebDriverを終了します。

 NPM(K)    PM(M)      WS(M)     CPU(s)      Id  SI ProcessName
 ------    -----      -----     ------      --  -- -----------
     23     8.28      23.83       0.02   23616   1 msedgedriver
動作しているMicrosoft Edge WebDriverの終了処理完了。

PS C:\Users\daichi>

こんな感じで、PowerShell SeleniumからJavaScriptコードを実行させるのはとても簡単だ。

PowerShellスクリプトにまとめる

上記処理をPowerShellスクリプトにまとめると次のようになる。

# WebDriver起動
webdriver_edge_start.ps1

# サンプルページをオープン
Set-SeUrl -Url https://getbootstrap.com/docs/4.0/examples/sign-in/

# JavaScriptを実行
Invoke-SeJavascript -Script '
    e = document.getElementsByTagName("body");
    e[0].setAttribute("style", "background:black");
'

#webdriver_edge_stop.ps1

JavaScriptが得意であれば、PowerShell Seleniumのコマンドレットを使うのではなく、全部上記スクリプトのInvoke-SeJavascriptコマンドレットにJavaScriptで処理を書いてしまう方が簡単だろう。この処理はそれだけ強力なものだ。

PowerShellを使う場合にはこうしたPowerShell Seleniumのパワーに加えて、JavaScriptをそのまま使うことができ、さらに.NETの機能をそのまま使うことができるという利点がある。これでMicrosoft EdgeのみならずOS側の処理に関してもある程度の自動化を行えるわけで、かなり強力な自動化ツールとして利用できるようになる。

付録

webdriver_edge_start.ps1

#!/usr/bin/env pwsh

#========================================================================
# Microsoft Edge WebDriverを起動する
#========================================================================

#========================================================================
# 動作しているMicrosoft Edge WebDriverをすべて終了
#========================================================================
webdriver_edge_stop.ps1

#========================================================================
# Seleniumモジュールがない場合にはインストール
#========================================================================
if (-Not (Get-InstalledModule -Name Selenium 2> $Null)) {
    'Seleniumモジュールをインストールします。'
    Install-Module -Name Selenium -AllowPrerelease -Force
    Get-InstalledModule -Name Selenium
}

#========================================================================
# Microsoft Edge WebDriverを起動
#========================================================================
'Microsoft Edge WebDriverを起動します。'
$Size = '1200,800'
if  (-Not (Start-SeDriver -Browser Edge -Size $Size 2> $Null 3> $Null))
{
    #================================================================
    # Microsoft EdgeとMicrosoft Edge WebDriverのバージョンが一致して
    # いないためにドライバが動作しなかった可能性がある。
    #================================================================

    #================================================================
    # 不要なドライバプロセスを終了
    #================================================================
    webdriver_edge_stop.ps1

    #================================================================
    # Microsoft Edgeのバージョン番号
    #================================================================
    $EdgeDir='C:\Program Files (x86)\Microsoft\Edge\Application\'
    $EdgeVersion=(  Get-ChildItem -Name $EdgeDir                    | 
                    Where-Object { $_ -NotMatch "[a-zA-Z]+" }       |
                    Select-Object -First 1                          )
                    # ↑ 【Select-Object -First 1の理由】
                    # 更新前のバージョンと更新後のバージョンが同時に
                    # 存在するタイミングがあるので、更新後のバージョン
                    # のみを取得するためにSelect-Objectを実行している。

    #================================================================
    # Microsoft Edge WebDriverダウンロードURLとデプロイ先パス
    #================================================================
    $DriverURL="https://msedgedriver.azureedge.net/$EdgeVersion/edgedriver_win64.zip"

    $SeModVer=(Get-InstalledModule -Name Selenium).Version -replace "-.+$",""
    $DriverDir="$env:HOME\Documents\powershell\Modules\Selenium\$SeModVer\assemblies"
    $DriverDownloadDir="$DriverDir\_download"

    #================================================================
    # WebDriverダウンロード用の一時ディレクトリを作成
    #================================================================
    New-Item        $DriverDownloadDir -ItemType Directory -Force

    #================================================================
    # Microsoft Edgeと同じバージョンのMicrosoft Edge WebDriverを
    # ダウンロード
    #================================================================
    "Microsoft Edge WebDriver version $EdgeVersion をダウンロードします。"
    curl            -get                                            `
                    -o      $DriverDownloadDir\edgedriver_win64.zip `
                    $DriverURL

    #================================================================
    # Microsoft Edge WebDriverをデプロイ
    #================================================================
    "Microsoft Edge WebDriver version $EdgeVersion をインストールします。"
    Expand-Archive  -Path $DriverDownloadDir\edgedriver_win64.zip   `
                    -Destination $DriverDownloadDir                 `
                    -Force

    Copy-Item       -Path $DriverDownloadDir\msedgedriver.exe       `
                    -Destination $DriverDir\msedgedriver.exe        `
                    -Force

    #================================================================
    # WebDriverダウンロード用の一時ディレクトリを削除
    #================================================================
    Remove-Item     $DriverDownloadDir -Recurse -Force

    #================================================================
    # Microsoft Edge WebDriverを起動する
    #================================================================
    if      (-Not (Start-SeDriver -Browser Edge -Size $Size 2> $Null 3> $Null)) 
    {
            #========================================================
            # 原因不明の起動不能
            #========================================================

            #========================================================
            # 不要なドライバプロセスを終了
            #========================================================
            webdriver_edge_stop.ps1

            Exit
    }
}
'Microsoft Edge WebDriverの起動処理完了。'

webdriver_edge_stop.ps1

#!/usr/bin/env pwsh

#========================================================================
# Microsoft Edge WebDriverを終了する
#========================================================================

#========================================================================
# WebDriverプロセスを終了
#========================================================================
if  (Get-Process -Name msedgedriver 2> $Null) 
{
    '動作しているMicrosoft Edge WebDriverを終了します。'
    Get-Process -Name msedgedriver 2> $Null

    # Microsoft Edge WebDriverを終了
    Stop-SeDriver 2> $Null

    # まだ動作しているほかのMicrosoft Edge WebDriverを終了
    if      (Get-Process -Name msedgedriver 2> $Null) 
    {
            Get-Process -Name msedgedriver 2> $Null | Stop-Process
    }

    '動作しているMicrosoft Edge WebDriverの終了処理完了。'
}