天気予報を取得してLINEに通知を送る その2


はじめに

プログラム初心者です。
GoogleAppScriptで書いてます。

前回の記事はこちら
https://qiita.com/taisatol/items/df399b47321bcb1e8d2a

構成

天気予報のWeb APIを取得
Livedoor天気:http://weather.livedoor.com/weather_hacks/webservice
Japan Weather Forecast xml:http://www.drk7.jp/weather/

必要なお天気情報を取り出しテキストを整形
 今日明日の天気
 最高/最低気温
 降水確率

LINE Notifyにテキストを送る

今回の課題

  • 天気予報APIから降水確率を取得
    • XML形式の読み込みに挑戦
  • livedoor天気のAPI内にある天気アイコンをLINEに表示させる
    • お天気アイコンの画像URLをLineNotifyに送る
    • 表示できませんでした(詳細は後述)

コード

main
//LineNotifyにメッセージを送信
function sendHttpPost(message){
  //Linenotify token
  var token = " -LineNotify Token- ";
  var options =
   {
     "method"  : "post",
     "payload" : "message=" + message,
     "headers" : {"Authorization" : "Bearer "+ token}

   };

   UrlFetchApp.fetch("https://notify-api.line.me/api/notify",options);
}

//メインルーチン
function whether_mail_day() {

  //Japan Weather Forecast xmlからXML形式のWEBAPIをリクエスト
  var response2 = UrlFetchApp.fetch(" -XML URL- ");
  var xml = XmlService.parse(response2.getContentText());

  //xmlから時間帯ごとの降水確率を取得 (pref.area.info.rainfallchance.period)
  var rainfallchance = xml.getRootElement().getChildren('pref')[0].getChildren('area')[1].getChildren('info');
  var rainfallchance2 = rainfallchance[0].getChildren('rainfallchance')[0].getChildren('period');


  //livedoor天気からjson形式のWEBAPIをリクエスト
  var response = UrlFetchApp.fetch(" -Json URL- ");
  var json=JSON.parse(response.getContentText());

  //jsonから最高/最低気温を取得 (forcasts.temperature.celsius)
  //日時(i),最高/最低(j)でforループ
  //気温がnullの場合--に変換
  var maxMin = ["max","min"];
  var Temp = new Array(2);
  for(var i = 0; i < 2; i++){
    Temp[i] = new Array(2)
    for(var j = 0; j < 2; j++){
      if(json["forecasts"][i]["temperature"][maxMin[j]] == null){
        Temp[i][j] = "--";
      }else{
        Temp[i][j] = json["forecasts"][i]["temperature"][maxMin[j]]["celsius"];
      }
    }  
  }

  //送信用文字列の作成
  //日時(i)、時間帯(j)でforループ
  var strBody = "天気予報";
  for(var i = 0;i < 2;i++){
    strBody = strBody + "\n" + date[i] + " : " + json["forecasts"][i]["telop"]
            + "\n" + "最低 : " + Temp[i][1] + "℃  最高 : " + Temp[i][0] + ""
            + "\n" + "降水確率";
    //降水確率の要素から値を取得
    for(var j = 0; j < rainfallchance2.length; j++) {
      strBody = strBody + "\n" + rainfallchance[i].getChildren('rainfallchance')[0].getChildren('period')[j].getAttribute("hour").getValue()
              + " : " + rainfallchance[i].getChildren('rainfallchance')[0].getChildren('period')[j].getText() + "";
    }
  };

  sendHttpPost(strBody);
}

実行結果

result
天気予報
mm/dd : 晴れ
最低 : --℃  最高 : XX℃
降水確率
00-06 : XX%
06-12 : XX%
12-18 : XX%
18-24 : XX%
mm/dd : 晴時々曇
最低 : XX℃  最高 : XX℃
降水確率
00-06 : XX%
06-12 : XX%
12-18 : XX%
18-24 : XX%

おわりに

わかったこと

  • GASにおけるXML形式の読み込み方
    • GASではid要素の名前を指定して読み込めないらしい(JavascriptではgetElementById()で実装できる?)
  • LineNotifyへお天気アイコンの画像を送れなかった
    • LineNotifyはjpgとpng形式のみ対応で、gif形式であるお天気アイコンは不可のようです

ちなみに画像をURLとして送る際はコードを以下のようにしたら動きました。

main
//LineNotifyにメッセージを送信
function sendHttpPost(message,url){
  //Linenotify token
  var token = "-LineNotify Token-";
  var payload =
      {
        "message" :message,
        "imageThumbnail" : url,
        "imageFullsize" :url
      };
  var options =
   {
     "method"  : "post",
     "payload" : payload,
     "headers" : {"Authorization" : "Bearer "+ token}

   };
  • パラメータimageThumbnailは必須
  • 画像はメッセージと別投稿になってしまう

課題

  • 2つの天気予報APIを使っているので、時間帯によっては日時の整合性が取れない場合が想定される
    • 日時を抜き出して比較する?
    • 日時が違っていた場合どう合わせるか?
  • 絵文字で天気を表示したい
    • 絵文字の表示方法
    • 取得した天気予報と表示する絵文字を対応させる
  • コードを綺麗にしたい
    • 特にXMLから要素を拾うときがスマートでない気がする 関数化してみたい

参考サイト様

http://unguis.cre8or.jp/web/6883
https://engineering.linecorp.com/ja/blog/detail/88
https://qiita.com/SKYS/items/39c0d300a6581f831023