前回まで、Webサイトからデータを取得してグラフのレンダリングを行い、最終的に描画したグラフを画像データとして保存するPowerShellスクリプトについて説明してきた。今回はそれらを全てまとめ、スクリプトを仕上げる。
→連載「PowerShell Core入門 - 基本コマンドの使い方」の過去回はこちらを参照。
グラフを書いて画像に保存するスクリプト「完全版」
前回はWebページからデータを取得した上で、Microsoft Edgeを起動し、Google Chartsを使ってグラフのレンダリングを行うところまでをPowerShellスクリプトにまとめた。今回は、レンダリングしたグラフを画像データファイルとして保存するところまで処理を行う。これで、当初目指した機能を満たすことになる。
まず先に、成果物「test-10.ps1」を掲載しておこう。
#!/usr/bin/env pwsh
#========================================================================
# 利用するファイルやURLなど
#========================================================================
$URL = 'https://www.data.jma.go.jp/obd/stats/data/mdrr/tem_rct/alltable/mxtemsad00.html'
$SrcFile = New-TemporaryFile
$OutFile = $env:HOMEDRIVE + $env:HOMEPATH + '\out.html'
$PNGFile = $env:HOMEDRIVE + $env:HOMEPATH + '\out.png'
#========================================================================
# 気温データを取得して整理する
#========================================================================
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">
// Google Visualization APIおよびコアチャートパッケージを読み込み
google.charts.load('current', {'packages':['corechart']});
// Google Visualization API読み込み完了後に実行
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
// データテーブルを作成
var data = new google.visualization.DataTable();
data.addColumn('string', '');
data.addColumn('number', '$DataName');
data.addRows([
"@
$GoogleChartsHTML2 = @"
]);
// チャートオプションを設定
var options = {'title':'$GraphTitle',
'width':500,
'height':300};
// 初期化およびチャートの生成
var chart = new google.visualization.BarChart(document.getElementById('chart_div'));
// チャートイメージをbase64エンコードされたPNG画像データとして出力
google.visualization.events.addListener(chart, 'ready', function () {
document.getElementById('chart_base64').innerHTML = chart.getImageURI();
});
// チャートを描画
chart.draw(data, options);
}
</script>
</head>
<body>
<div id="chart_div"></div>
<div id="chart_base64"></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 > $OutFile
$GraphData >>$OutFile
$GoogleChartsHTML2 >>$OutFile
#========================================================================
# WebDriver起動
#========================================================================
webdriver_edge_start.ps1
#========================================================================
# Microsoft EdgeでGoogle Charts用のHTMLをオープン
#========================================================================
$FileURL = "file:///" + $OutFile.Replace('\','/')
'Microsoft Edgeでグラフを描画します。'
Set-SeUrl -Url $FileURL
#========================================================================
# 描画されたグラフをBase64エンコードされたPNGデータとして取得
#========================================================================
'描画したグラフをBase64エンコードされたPNGデータとして取得します。'
$Element = Get-SeElement -By XPath -Value '//*[@id="chart_base64"]'
$Base64 = $Element.Text -replace 'data:image/png;base64,',''
#========================================================================
# Base64エンコードデータをデコードしてファイルへ保存
#========================================================================
'Base64エンコードされたPNGデータをデコードして保存します。'
$Bytes = [Convert]::FromBase64String($Base64)
[IO.File]::WriteAllBytes($PNGFile, $Bytes)
#========================================================================
# WebDriverを終了
#========================================================================
webdriver_edge_stop.ps1
#========================================================================
# 作業用の一時ファイルを削除
#========================================================================
Remove-Item $SrcFile
Remove-Item $OutFile
PowerShellからは、.NETの機能も含めてさまざまな機能を利用することができる。このくらいの長さのスクリプトでもこういった処理ができてしまうところがPowerShellの便利な点の一つだ。