AppleScriptでJSONをパースして電力の使用状況グラフを作る

3/22より、東京電力から電力の使用状況グラフというのが公開されるようになり、電力の使用実績が見えるようになった。しかし、このグラフで表示できるのは当日のみ。昨日の使用状況を確認しようと次の日にアクセスしても、当日のグラフしか表示されないのである。不便...。

そんなことを思っていると、翌日には東京電力 電力供給状況APIが公開されていた。(すごいスピード感)これを使えば、上記の不便も含めた諸々の問題を一気に解決してくれるのだ。

上記URLにアクセスすると、JSON形式のデータを返してくれる。快適な仕様だ。

ところで、過去のデータを取得してグラフを描こと思った時に、自分の環境で手っ取り早く使えるのは、NeoOfficeOpenOffice系列)だったりする。Officeでグラフを描くためには、JSON形式のデータから必要な項目を抜き出して、CSV形式に変換しておく必要がある。それを手作業では、ほとんどやる気にならない。どうするか?自分の場合は、おなじみのAppleScriptでやってみることにした。

JSONをパースする

果たして、AppleScriptJSONをうまく扱えるのか?そう思って調べてみると、見事に扱っている方を見つけた!

なるほど。JSONとレコード*1が似ていることを利用して、Run Scriptで一気にレコードに変換してパースしてしまうという発想、素晴らしいです!


早速、なるべく一般的なJSONに対応すべく、以下のようにコーディングしてみた。


"[ { \"saving\": false, \"hour\": 0, \"capacity_updated\": \"2011-04-04 16:05:00\", \"month\": 4, \"usage_updated\": \"2011-04-04 16:30:42\", \"entryfor\": \"2011-04-04 15:00:00\", \"capacity_peak_period\": 18, \"year\": 2011, \"usage\": 2878, \"capacity\": 4000, \"day\": 5 }, { \"saving\": false, \"hour\": 1, \"capacity_updated\": \"2011-04-04 16:05:00\", \"month\": 4, \"usage_updated\": \"2011-04-04 17:05:42\", \"entryfor\": \"2011-04-04 16:00:00\", \"capacity_peak_period\": 18, \"year\": 2011, \"usage\": 2738, \"capacity\": 4000, \"day\": 5 } ]" my record_from_json(result)

--jsonをレコードに変換する
on record_from_json(a_json)
--環境設定 >> 編集 >> 詳細:「文字列中のタブや改行をエスケープ」チェックあり だと読み易い
{{space, ""}} --スペース削除
result & {{"{\"", "{"}, {",\"", ","}, {"\r\"", "\r"}, {"\n\"", "\n"}, {"\":", ":"}} --ラベルのダブルクォート削除
result & {{"[", "{"}, {"]", "}"}} --[]{}に置き換え
result & {{"\r", ""}, {"\n", ""}} --改行削除
run script my every_replace(a_json, result)
end record_from_json

--sourceTextに対してpair_listが指定する置き換えを実行する
-- every_replace(sourceText, {{text1, text2}, {text3, text4}})
--以下と同等
-- replace(sourceText, text1, text2)
-- replace(sourceText, text3, text4)
on every_replace(sourceText, pair_list)
repeat with pair in pair_list
set sourceText to replace(sourceText, pair's item 1, pair's item 2)
end repeat
end every_replace

--sourceTexttext1text2に置き換えた文字列を返す
on replace(sourceText, text1, text2)
join(split(sourceText, text1), text2)
end replace

--sourceTextdelimiterで区切ったリストを返す
on split(sourceText, delimiter)
if sourceText = "" then return {}
set oldDelimiters to AppleScript's text item delimiters
set AppleScript's text item delimiters to delimiter
set theList to sourceText's text items
set AppleScript's text item delimiters to oldDelimiters
return theList
end split

--sourceListdelimiterを挿入して結合した文字列を返す
on join(sourceList, delimiter)
set oldDelimiters to AppleScript's text item delimiters
set AppleScript's text item delimiters to delimiter
set theText to sourceList as text
set AppleScript's text item delimiters to oldDelimiters
return theText
end join

JSONを記述する全てのケースに対応できているかは怪しいが、少なくとも今回の東京電力の電力供給状況APIから受け取るJSONをパースするには、これで問題なさそう。

東京電力 電力供給状況APIとの連携

これで、JSONはレコードに変換され、AppleScriptで自由に取り扱えるようになった。あとは自分が欲しいデータ型式に加工するだけ。
自分の希望は、これまでの全ての期間の需給状態を連続したグラフで表示して、その遷移を見ること。果たしてどんなグラフになるのか?


property API_URL : "http://tepco-usage-api.appspot.com/"
property SP : ","

set csvs to {"日時,使用量,供給可能量"} --列タイトル
repeat with y from 2011 to 2011
repeat with m from 3 to 4
set json to do shell script "curl " & API_URL & y & "/" & m & ".json" --json形式の需給データを得る
repeat with json_item in my record_from_json(json) --jsonからcsvに変換する
if json_item's saving then
set mark to "●"
else
set mark to "○"
end if
set Y_label to json_item's day & mark & json_item's hour as text
set csvs's end to Y_label & SP & json_item's usage & SP & json_item's capacity
end repeat
end repeat
end repeat

my save_text(my join(csvs, return), my temp_file("tepco.csv")) --csvを一時ファイルとして保存
my open_file(my temp_file("tepco.csv"), "NeoOffice") --csvNeoOfficeで開く



--ホームフォルダの一時ファイルとして名称f_nameのパスを返す
on temp_file(f_name) (path to temporary items from user domain as text) & f_name
end temp_file

--テキストデータa_textを、ファイルパスf_pathに保存する
on save_text(a_text, f_path) do shell script "echo " & quoted form of a_text & ">" & f_path's POSIX path
end save_text

--ファイルパスf_pathをアプリケーションapp_nameで開く
on open_file(f_path, app_name) tell application app_name
activate
open f_path as alias
end tell
end open_file

--jsonをレコードに変換する
on record_from_json(a_json) --環境設定 >> 編集 >> 詳細:「文字列中のタブや改行をエスケープ」チェックあり だと読み易い
{{space, ""}} --スペース削除
result & {{"{\"", "{"}, {",\"", ","}, {"\r\"", "\r"}, {"\n\"", "\n"}, {"\":", ":"}} --ラベルのダブルクォート削除
result & {{"[", "{"}, {"]", "}"}} --[]{}に置き換え
result & {{"\r", ""}, {"\n", ""}} --改行削除
run script my every_replace(a_json, result) end record_from_json

--sourceTextに対してpair_listが指定する置き換えを実行する
-- every_replace(sourceText, {{text1, text2}, {text3, text4}})
--以下と同等
-- replace(sourceText, text1, text2)
-- replace(sourceText, text3, text4)
on every_replace(sourceText, pair_list) repeat with pair in pair_list
set sourceText to replace(sourceText, pair's item 1, pair's item 2) end repeat
end every_replace

--sourceTexttext1text2に置き換えた文字列を返す
on replace(sourceText, text1, text2) join(split(sourceText, text1), text2) end replace

--sourceTextdelimiterで区切ったリストを返す
on split(sourceText, delimiter) if sourceText = "" then return {} set oldDelimiters to AppleScript's text item delimiters
set AppleScript's text item delimiters to delimiter
set theList to sourceText's text items
set AppleScript's text item delimiters to oldDelimiters
return theList
end split

--sourceListdelimiterを挿入して結合した文字列を返す
on join(sourceList, delimiter) set oldDelimiters to AppleScript's text item delimiters
set AppleScript's text item delimiters to delimiter
set theText to sourceList as text
set AppleScript's text item delimiters to oldDelimiters
return theText
end join

試用

  • 早速、実行ボタンを押してみる。
  • 待つこと10秒、NeoOfficeが起動した。
  • CSVファイルのインポート画面が表示されるので、区切り記号にComma(カンマ)をチェックする。

  • データを読み込んで、グラフを追加してみた。(これは手作業)

  • 赤いラインが供給可能な最大電力。
  • 棒グラフは1時間ごと使用電力。
  • X軸の日時で●になっている部分が計画停電を実施した時間。
  • 全体を縮小して一覧してみた。

  • グラフだけ拡大するとこんな感じ。


オチ

東京電力 電力供給状況APIのページで紹介される以下のサイトがあった...。


全期間のデータを一括してCSVで取得できるAPIも公開されていた...。


これでいいじゃん!

分析

  • 3/15から3/22の期間は不明だが、果たして計画停電は必要だったのだろうか?
  • 3/23・3/25は夕方の計画停電を実施したが、3/24は実施していない。
  • 3/24に実施しないで済んでしまうのなら、3/23・3/25の計画停電も不要だった気がする。
  • また、グラフのデータには漏れているが、3/28も18:20から20:00まで計画停電が実施された。(自分の地区が停電したので記憶している)
  • なぜ、そんなタイミングで実施したのか?十分に足りている気がする。

疑問

  • 東京電力計画停電によって、電力不足をアピールしたかったのだろうか?
  • 3/17に大々的に報道された大規模停電を回避するための節電要請のように、誠意を持って広く節電協力を呼びかけるだけで良かったのではないか?

その心は

なるほど。この動画を見て、計画停電の効能を理解できたような気がした。


  • 原発が使えなくなると...
    • 電力が不足するんだ、
    • 計画停電さえ必要になるんだ、
    • 信号機も病院も消灯するんだ、
    • 電気が不足すると大変な事態になるんだ、
  • 結果として、消極的原発容認派*2を増やす効果があった。
  • それは、原発反対派の対抗勢力になりうる。
  • つまり、電力会社の味方が増加した。
  • 世論の流れを原発容認の方向へ接近させた。
  • 各メディアは、計画停電の報道にそれなりの時間を割くようになる。
    • 相対的に、原発事故の実況・放射能汚染などの報道割合が減少する。
  • 計画停電のダメな所を指摘する。別の解決策を模索する。多くの人々が議論し始める。
  • この日記でも取り上げたように、計画停電に絡んだ話題が多くなった。(この日記も、策にハマったのかも)
  • 相対的に、原発に関する話題は、減少する結果となる。


計画停電は注意を逸らす囮だったのか?

*1:AppleScript連想配列のようなもので、PerlRubyのハッシュ、Pythonの辞書(dictionary)と同等。

*2:原発はない方が良い。しかし、代替手段のない現状では止む無し。現状維持なら仕方ない。という考えの派閥。