前回までに、グラフのレンダリングにはGoogle Chartsを使うこと、描画するデータはWebからダウンロードして加工することを説明した。この2つの処理を組み合わせると、PowerShellスクリプトからGoogle Chartsを使ったグラフの生成を自動化することができる。今回は、この部分の処理について取り上げる。

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

東京都の気温を得るPowerShellスクリプト

前回作成したPowerShellスクリプト「test-6.ps1」は次の通りだ。

#!/usr/bin/env pwsh

#========================================================================
# 気温データを取得して整理する
#========================================================================
$URL = 'https://www.data.jma.go.jp/obd/stats/data/mdrr/tem_rct/alltable/mxtemsad00.html'
$SrcFile = New-TemporaryFile

curl        --get $URL                                      > $SrcFile 2> $null

#========================================================================
# 東京の気象データを抽出
#========================================================================
# 東京都の気象データを抽出
$s = (Get-Content $SrcFile | Select-String '>東京都</td')

# HTMLタグなどの不要なデータを削除
$s = $s     -replace '</[^>]+>',' '                         `
    -replace '<[^>]+>',''                           `
    -replace '([^)]+)[*]*',''

# 地名と気温を抽出
foreach ($l in $s) {
    $a = $l -split " "
    "['" + $a[2] + "'," + $a[3] + "],"
}

#========================================================================
# 作業用の一時ファイルを削除
#========================================================================
Remove-Item $SrcFile

このスクリプトを実行すると、次のように東京都の現在の気温を取得できる。

PS C:\Users\daichi> .\test-6.ps1
['小河内',19.8],
['青梅',22.7],
['練馬',23.8],
['八王子',21.8],
['府中',22.4],
['東京',22.2],
['江戸川臨海',18.9],
['羽田',20.8],
['大島',19.8],
['大島北ノ山',20.0],
['新島',20.4],
['神津島',19.1],
['三宅島',19.8],
['三宅坪田',21.0],
['八重見ヶ原',20.1],
['八丈島',19.5],
['父島',21.5],
PS C:\Users\daichi>

これは、対象とするWebページごとにアドホックに作るようなものだ。しかし、ここまでできればGoogle Chartsでグラフをレンダリングするのは簡単だ。

東京都の気温をグラフに描くPowerShellスクリプト

先に書き換えたPowerShellスクリプト「test-7.ps1」を掲載しておく。

#!/usr/bin/env pwsh

#========================================================================
# 気温データを取得して整理する
#========================================================================
$URL = 'https://www.data.jma.go.jp/obd/stats/data/mdrr/tem_rct/alltable/mxtemsad00.html'
$SrcFile = New-TemporaryFile

curl        --get $URL                                      > $SrcFile 2> $null

#========================================================================
# Google Charts用HTMLの用意
#========================================================================
$DataName = '現在の気温'
$GraphTitle = '東京都の現在の気温'

$GoogleChartsHTML1 = @"
<html>
  <head>
    <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
    <script type="text/javascript">
      // Load the Visualization API and the corechart package.
      google.charts.load('current', {'packages':['corechart']});

      // Set a callback to run when the Google Visualization API is loaded.
      google.charts.setOnLoadCallback(drawChart);

      // Callback that creates and populates a data table,
      // instantiates the pie chart, passes in the data and
      // draws it.
      function drawChart() {
        // Create the data table.
        var data = new google.visualization.DataTable();
        data.addColumn('string', '');
        data.addColumn('number', '$DataName');
        data.addRows([
"@

$GoogleChartsHTML2 = @"
        ]);

        // Set chart options
        var options = {'title':'$GraphTitle',
                       'width':500,
                       'height':300};

        // Instantiate and draw our chart, passing in some options.
        var chart = new google.visualization.BarChart(document.getElementById('chart_div'));
        chart.draw(data, options);
      }
    </script>
  </head>
  <body>
    <div id="chart_div"></div>
  </body>
</html>
"@

#========================================================================
# 東京の気象データを抽出
#========================================================================
# 東京都の気象データを抽出
$s = (Get-Content $SrcFile | Select-String '>東京都</td')

# HTMLタグなどの不要なデータを削除
$s = $s     -replace '</[^>]+>',' '                         `
    -replace '<[^>]+>',''                           `
    -replace '([^)]+)[*]*',''

# 地名と気温を抽出
$GraphData = ""
$Indent = "          "
foreach ($l in $s) {
    $a = $l -split " "
    if ($GraphData) {
            $GraphData = $GraphData + ",['" + $a[2] + "'," + $a[3] + "]"
    }
    else {
            $GraphData = "$Indent['" + $a[2] + "'," + $a[3] + "]"
    }
}

#========================================================================
# Google Charts用のHTMLを出力
#========================================================================
$GoogleChartsHTML1
$GraphData
$GoogleChartsHTML2

#========================================================================
# 作業用の一時ファイルを削除
#========================================================================
Remove-Item $SrcFile

このPowerShellスクリプトを実行すると、気象庁のWebページからダウンロードしてきた気温データを加工して、Google ChartsでグラフをレンダリングするためのHTMLが生成される。

PowerShellスクリプト書き換えのポイント

PowerShellスクリプトで書き換えたポイントを説明する。まず次の2カ所だ。「ヒアドキュメント」を使っている。

Google Charts用HTMLをヒアドキュメントで書いて変数で保持 その1

$GoogleChartsHTML1 = @"
<html>
  <head>
    <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
    <script type="text/javascript">
      // Load the Visualization API and the corechart package.
      google.charts.load('current', {'packages':['corechart']});

      // Set a callback to run when the Google Visualization API is loaded.
      google.charts.setOnLoadCallback(drawChart);

      // Callback that creates and populates a data table,
      // instantiates the pie chart, passes in the data and
      // draws it.
      function drawChart() {
        // Create the data table.
        var data = new google.visualization.DataTable();
        data.addColumn('string', '');
        data.addColumn('number', '$DataName');
        data.addRows([
"@

Google Charts用HTMLをヒアドキュメントで書いて変数で保持 その2

$GoogleChartsHTML2 = @"
        ]);

        // Set chart options
        var options = {'title':'$GraphTitle',
                       'width':500,
                       'height':300};

        // Instantiate and draw our chart, passing in some options.
        var chart = new google.visualization.BarChart(document.getElementById('chart_div'));
        chart.draw(data, options);
      }
    </script>
  </head>
  <body>
    <div id="chart_div"></div>
  </body>
</html>
"@

Google ChartsはHTML+JavaScriptで記述するので、PowerShellスクリプトにそのためのテンプレート的なデータを持っておく必要がある。複数行にまたがるテキストデータを保持する場合にはヒアドキュメントを使う。

PowerShellでは「@"~"@」が変数展開ありのヒアドキュメント、「@'~'@」が変数展開なしのヒアドキュメントだ。ラベルなどをあとから書き換えやすいように変数に保持しておきたいので、ここでは変数展開ありの「@"~"@」で記述してある。

ヒアドキュメントは、こんな感じでPowerShellスクリプトに複数行にまたがるテキストデータを保持しておくのに便利なので、ぜひ覚えておきたい機能だ。

次に、東京都の気温データを出力していた部分を、いったん変数に保持するように書き換えている。

$GraphData = ""
$Indent = "          "
foreach ($l in $s) {
    $a = $l -split " "
    if ($GraphData) {
            $GraphData = $GraphData + ",['" + $a[2] + "'," + $a[3] + "]"
    }
    else {
            $GraphData = "$Indent['" + $a[2] + "'," + $a[3] + "]"
    }
}

そして最後にヒアドキュメントで保持しておいたGoogle Charts用のHTML+JavaScriptと、上記で作成した気温データを出力している。

$GoogleChartsHTML1
$GraphData
$GoogleChartsHTML2

これが今回書き換えた内容だ。一つ一つはシンプルな書き換えだが、これで十分に機能するものを作ることができる。

実行してみる

さっそく実行してみよう。まず、次のようにPowerShellスクリプトを実行して出力をファイルに保存する。

.\test-7.ps1 > chart.html

なお、この実行では次のようなHTMLデータが生成されている。

<html>
  <head>
    <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
    <script type="text/javascript">
      // Load the Visualization API and the corechart package.
      google.charts.load('current', {'packages':['corechart']});

      // Set a callback to run when the Google Visualization API is loaded.
      google.charts.setOnLoadCallback(drawChart);

      // Callback that creates and populates a data table,
      // instantiates the pie chart, passes in the data and
      // draws it.
      function drawChart() {
        // Create the data table.
        var data = new google.visualization.DataTable();
        data.addColumn('string', '');
        data.addColumn('number', '現在の気温');
        data.addRows([
          ['小河内',19.8],['青梅',22.7],['練馬',23.8],['八王子',21.8],['府中',22.4],['東京',22.2],['江戸川臨海',18.9],['羽田',20.8],['大島',19.8],['大島北ノ山',20.0],['新島',20.4],['神津島',19.1],['三宅島',19.8],['三宅坪田',21.0],['八重見ヶ原',20.1],['八丈島',19.5],['父島',21.5]
        ]);

        // Set chart options
        var options = {'title':'東京都の現在の気温',
                       'width':500,
                       'height':300};

        // Instantiate and draw our chart, passing in some options.
        var chart = new google.visualization.BarChart(document.getElementById('chart_div'));
        chart.draw(data, options);
      }
    </script>
  </head>
  <body>
    <div id="chart_div"></div>
  </body>
</html>

このファイルをMicrosoft Edgeで開くと次のようにグラフがレンダリングされる。

  • Google Chartsの機能でグラフをレンダリング

    Google Chartsの機能でグラフをレンダリング

  • 実際にレンダリングに使われていることを確認

    実際にレンダリングに使われていることを確認

簡単な書き換えだが目的に近づくことができた。

次はグラフを画像データに変換する

次はこのグラフデータを画像に変換する処理を作っていく。これまでにこの連載で取り上げてきた方法を使うのであれば、Microsoft Edgeをヘッドレスモードで起動してWebページごと画像にしてしまうところなのだが、この方法はGoogle Charts側が動作しないので使うことができない。

次回は、PowerShell Seleniumを経由してMicrosoft Edgeを操作することでグラフデータを画像データに変換していく。