2022年5月3日火曜日

【GAS】気象庁 API から取得した天気予報を LINE にプッシュ通知する

いかに負荷なく情報を得るか。そういう意味で LINE のプッシュ通知は有用ですね。

父と母がそれぞれ提供元の異なる天気予報を見てどちらを信じるかいつももめているので(笑)、気象庁の天気予報を LINE にプッシュ通知する GAS(Google Apps Script)を作ってみました。

あくまで公式ではないという体の気象庁 API のおかげで、こういうのは非常にすっきり作れるようになりましたね。備忘録がてら作り方を。


データの取得元は以下になります。

・今日・明日・明後日の天気予報(福島地方気象台

・天気予報テロップ番号


また、天気予報の地域は以下よりエリアコードを探してください。



なお、LINE Developers の設定については検索すればたくさん出てくるかと思いますので省略します。

今回 LINE の Messaging API で使うのはプッシュメッセージのみです。リプライは使いませんので、Webhook や GAS 側でのウェブアプリケーションの公開の手順は必要ありません(当たり前ですが使う場合は必要)。


▼ スクリプトの作成

まずは天気予報の JSON の取得から整形を行うスクリプトです。

  1. function getForecastData() {
  2. //JSONデータの取得
  3. const url = "https://www.jma.go.jp/bosai/forecast/data/forecast/070000.json";
  4.  
  5. let response = "";
  6. try {
  7. response = UrlFetchApp.fetch(url);
  8. } catch(e) {
  9. return response;
  10. }
  11. let data = JSON.parse(response.getContentText());
  12.  
  13. //後から使う変数
  14. let forecast = [];
  15. let date = "";
  16. let num = "";
  17.  
  18. //基礎情報
  19. forecast.push("発表者:" + data[0]["publishingOffice"] + "\n");
  20. date = data[0]["reportDatetime"];
  21. date = date.replace("T", " ");
  22. date = date.replace(":00+09:00", "");
  23. forecast.push("報告日時:" + date + "\n\n");
  24. forecast.push("【" + data[0]["timeSeries"][0]["areas"][1]["area"]["name"] + "】\n");
  25.  
  26. //今日・明日・明後日の天気
  27. let weather = "";
  28. let rNum = "";
  29. const telopSh = SpreadsheetApp.openById("天気予報テロップ番号のスプレッドシート ID").getSheetByName("telop");
  30. const telop = Array.prototype.concat.apply([], telopSh.getRange(2, 1, 122, 1).getValues());
  31. let day = "";
  32.  
  33. num = data[0]["timeSeries"][0]["timeDefines"].length
  34. for(let i = 0; i < num; i++) {
  35. rNum = telop.indexOf(Number(data[0]["timeSeries"][0]["areas"][1]["weatherCodes"][i]));
  36. weather = telopSh.getRange(rNum + 2, 2).getValues();
  37. switch(i) {
  38. case 0:
  39. day = "今日"
  40. break;
  41. case 1:
  42. day = "明日"
  43. break;
  44. case 2:
  45. day = "明後日"
  46. break;
  47. }
  48. forecast.push(day + "の天気:" + weather + "\n");
  49. forecast.push("概況:" + data[0]["timeSeries"][0]["areas"][1]["weathers"][i] + "\n");
  50. forecast.push("風:" + data[0]["timeSeries"][0]["areas"][1]["winds"][i] + "\n");
  51. //forecast.push("波の高さ" + data[0]["timeSeries"][0]["areas"][1]["waves"][i] + "\n");
  52. forecast.push("\n");
  53. }
  54.  
  55. //降水確率
  56. forecast.push("■降水確率\n");
  57. num = data[0]["timeSeries"][1]["timeDefines"].length
  58. for(let j = 0; j < num; j++) {
  59. date = data[0]["timeSeries"][1]["timeDefines"][j];
  60. date = date.replace("T", " ");
  61. date = date.replace(":00+09:00", "");
  62. forecast.push(date + "|" + data[0]["timeSeries"][1]["areas"][1]["pops"][j] + "%\n")
  63. }
  64. forecast.push("\n");
  65.  
  66. //気温
  67. forecast.push("■小名浜の気温\n");
  68. num = data[0]["timeSeries"][2]["timeDefines"].length
  69. for(let k = 0; k < num; k++) {
  70. date = data[0]["timeSeries"][2]["timeDefines"][k];
  71. date = date.replace("T", " ");
  72. date = date.replace(":00+09:00", "");
  73. forecast.push(date + "|" + data[0]["timeSeries"][2]["areas"][1]["temps"][k] + "℃\n");
  74. }
  75.  
  76. return forecast.join("");
  77. }

3行目の URL は取得したい地域に合わせて変更してください。URL 末尾の「.json」前の6ケタのエリアコードを変更します。

今回の場合、福島地方気象台(070000)発表の浜通りの天気予報、降水確率及び小名浜の気温を取得しています。

元の JSON には他にもデータが含まれていますので必要なものは適宜追加・削除してください。階層が若干深めですが、丁寧に見ていけばそれほどややこしくはないと思います。

ただ更新されるタイミングによってデータの数が変わったりするので、その辺もハンドリングできるようにしておかないといろいろずれます。

29行目は天気予報テロップ番号と対応する天気が記載されたスプレッドシートのIDになります。シート名は「telop」になっています。上のスプレッドシートをコピーして使用できます(共有リクエストではなく、コピーして使ってください)。


つぎに整形したデータを LINE でプッシュ通知するスクリプトです。ひとつのファイルで作ってしまってもいいのですが、私は分けた方が見やすいので分けています。

  1. const ACCESS_TOKEN = "チャンネルアクセストークン";
  2.  
  3. const PUSH = "https://api.line.me/v2/bot/message/push";
  4.  
  5. function push() {
  6. let postData = {
  7. "to" : "LINE ユーザー ID",
  8. "messages" : [
  9. {
  10. "type" : "text",
  11. "text" : getForecastData()
  12. }
  13. ]
  14. };
  15. // リクエストヘッダ
  16. const headers = {
  17. "Content-Type" : "application/json; charset=UTF-8",
  18. "Authorization" : "Bearer " + ACCESS_TOKEN
  19. };
  20. // POSTオプション作成
  21. const options = {
  22. "method" : "POST",
  23. "headers" : headers,
  24. "payload" : JSON.stringify(postData)
  25. };
  26.  
  27. return UrlFetchApp.fetch(PUSH, options);
  28. }

1行目の「チャンネルアクセストークン」、7行目の「LINE ユーザー ID」を記載します。

LINE のユーザー ID は LINE ID とは異なります。LINE Developers 内、Channel の Basic settings に載っています。

ちなみに、自分以外のユーザーやグループに対してメッセージを送りたい場合はユーザー ID やグループ ID を取得する必要がありちょっと手間がかかります。これも GAS 作ってしまうのが一番簡単そうなので後ほど作っておきたいと思います(→ 作りました)。

これで一通り完成。push 関数を実行することで天気予報が LINE に届きます。


▼ 送ってみる


こんな感じになります。

ちなみに、今回作ってみて驚いたのが天気予報の種類の多さです。100種類以上あるのですね。


トリガー設定をしておけば定時に天気予報を知ることができます。公式の記載では天気予報の更新は毎日5:00、11:00、17:00にされるようです(気象台により異なるところもあるみたいです)。