前回、スクリーンショットを保存するファイルを指定できるようにした。しかし、そのままだと実際には結構使いにくいところがある。今回は何が問題なのかと、その改善方法について説明する。

前回の成果物を確認

Webページのスクリーンショットを撮るPowerShellスクリプト「getss.ps1」は、前回までの取り組みでほぼ完成した。これで特定のWebページのスクリーンショットを自動的に取って利用する、といったスクリプトを運用することができる。

作ったgetss.ps1は次の通りだ。

#!/usr/bin/env pwsh

#========================================================================
# スクリーンショットを取得する
#========================================================================

#========================================================================
# 引数を処理
#   -URI uri        スクリーンショットを取得するリソースのURI
#   -Width width    スクリーンショットの幅
#   -Height height  スクリーンショットの高さ
#   -OutputFilePath path スクリーンショットを保存するファイル
#   -Agent      Webサーバへ送るUser-Agent文字列を指定
#========================================================================
Param(
    [Parameter(Mandatory=$false)][String]$URI = "desktop:",
    [Int]$Width = 1200,
    [Int]$Height = 800,
    [String]$OutputFilePath = "${env:HOME}/ss.png",
    [String]$Agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
)

#========================================================================
# スクリーンショットの取得に利用するアプリケーションほか
#========================================================================
$msedge='C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe'
$snippingtool='SnippingTool.exe'
$curl='C:\Windows\System32\curl.exe'

#========================================================================
# どの方法でスクリーンショットを取得するか判断
#========================================================================
switch  -Wildcard ($URI)
{
    'http*'
    {
        #========================================================
        # Microsoft Edgeを使って取得
        #========================================================
        $method='msedge'
        break
    }

    'desktop:*'
    {
        #========================================================
        # Snipping Toolを使って取得
        #========================================================
        $method='snippingtool'
        break
    }

    default
    {
        $method='none'
    }
}

#========================================================================
# スクリーンショットを撮るリソース種類の特定
#========================================================================
$contenttype='none'
switch  -Wildcard ($URI)
{
    #================================================================
    # コンテンツの種類を特定
    #================================================================
    'http*.html'
    {
        $contenttype='text/html'
        break
    }
    'http*.htm'
    {
        $contenttype='text/html'
        break
    }
    'http*.shtml'
    {
        $contenttype='text/html'
        break
    }
    'http*/'
    {
        $contenttype='text/html'
        break
    }
    'http*.txt'
    {
        $contenttype='text/plain'
        break
    }
    'http*.csv'
    {
        $contenttype='text/csv'
        break
    }
    'http*csv=1'
    {
        $contenttype='text/csv'
        break
    }
    'http*.pdf'
    {
        $contenttype='application/pdf'
        break
    }
    'http*.zip'
    {
        $contenttype='application/zip'
        break
    }
    default
    {
        $contenttype=(  & $curl     --location      `
                        -A $Agent       `
                        -Ss -I          `
                        $URI            |
                Select-String   "^Content-Type:"    )
        break
    }
}

#========================================================================
# スクリーンショットが取れないWebリソースの場合、代わりに
# http://example.com/ のスクリーンショットを取っておく
#========================================================================
switch  -Wildcard ($contenttype)
{
    #================================================================
    # コンテンツの種類を特定
    #================================================================
    '*text/html*'
    {
        break
    }
    '*text/plain*'
    {
        break
    }
    '*/*'
    {
        $URI='http://example.com/'
        break
    }
}

#========================================================================
# スクリーンショットを取得
#========================================================================
switch  ($method)
{
    #================================================================
    # Microsoft Edgeを使って取得
    #================================================================
    'msedge'
    {
        $o1='--headless'
        $o2='--screenshot="' + $OutputFilePath + '"'
        $o3="--window-size=$Width,$Height"
        $o4='--user-agent="$Agent"'
        $o5='--hide-scrollbars'

        Start-Process   -FilePath $msedge           `
                -ArgumentList $o1,$o2,$o3,$o4,$o5,$URI  `
                -Wait
        break
    }

    #================================================================
    # Snipping Toolを使って取得
    #================================================================
    'snippingtool'
    {
        Start-Process   -FilePath $snippingtool 
        # ※ -Waitは指定しても機能しない
        break
    }
}

結構スクリプトが長くなってきたが、処理自体はシンプルなことしか行っていない。このように必要な機能だけまとめたスクリプトを見通しの良い状態に保っておくことが、PowerShellスクリプトを利用していく上でポイントの一つだ。複雑にしてしまうと将来の自分を困らせることになる。

実際に使うと……?

getss.ps1を実際に使っていくと、ある問題に遭遇すると思う。次のようにコマンドを実行しても、指定したファイルにスクリーンショットが保存されないのだ。

PS C:\Users\daichi> getss.ps1 -OutputFilePath .\Desktop\ss.png https://news.mynavi.jp/techplus/
PS C:\Users\daichi>

これは、指定されたパスをそのままMicrosoft Edgeに渡していることが原因だ。上記コマンドラインでは、スクリーンショットを保存するファイルのパスを相対パスで指定している。しかし、Microsoft Edgeのヘッドレスモードは相対パスで指定されたパスを扱わない。ファイルパスは絶対パスで指定しないと機能してくれないのだ。

コマンドラインから使う場合、パスを絶対パスで指定するというのは面倒だ。スクリプトから使う場合はパスを明確にした方がよいのだが、自分だけが使うようなスクリプトならカレントディレクトリにそのまま生成して使ってしまいたくもなる。相対パスで指定できないと面倒なのだ。

そこで、今回はスクリーンショットを保存するファイルを相対パスで指定できるように書き換える。

相対パスを絶対パスに変換する

この記事は
Members+会員の方のみ御覧いただけます

ログイン/会員登録(無料)

会員サービスの詳細はこちら