Google Apps Script から tenki.jp をスクレイピングしてみる

前回、「OpenWeatherMap」の天気APIを使いましたが、実際の気温と全然違っていたので、

精度が高い、「tenki.jp」のWEB表示をスクレイピングするようにしました。

朝は6時、昼は12時、夜は18時のデータを取得するようにしています。

var sheet = SpreadsheetApp.getActiveSheet();

function getTenkiHtml(){

  sheet.clear();

  var response = UrlFetchApp.fetch("https://tenki.jp/forecast/[各都市で変わるURL]/3hours.html");

  var html = response.getContentText();

  var regexp_table = /<table id="forecast-point-3h-today" class="forecast-point-3h">([\s\S]*?)<\/table>/i;
  var match_table = regexp_table.exec(html);
  var tenki_table = match_table[1];

  var regexp_hour = /<tr class="hour">([\s\S]*?)<\/tr>/i;
  var match_hour = regexp_hour.exec(tenki_table);
  var tenki_hour = match_hour[1];

  var tenki_hour_arr = tenki_hour.split("</td>");
  sheet.getRange(1, 1).setValue("時間");
  for(var i=0;i<tenki_hour_arr.length;i++){
    var item = tenki_hour_arr[i];
    item = delTag(item);
    item = trim(item);
    sheet.getRange(1, i+2).setValue(item);
  }

  var regexp_weather = /<tr class="weather">([\s\S]*?)<\/tr>/i;
  var match_weather = regexp_weather.exec(tenki_table);
  var tenki_weather = match_weather[1];

  var tenki_weather_arr = tenki_weather.split("</td>");
  sheet.getRange(2, 1).setValue("天気");
  for(var i=0;i<tenki_weather_arr.length;i++){
    var item = tenki_weather_arr[i];
    item = item.replace(/天気/g, '');
    item = delTag(item);
    item = trim(item);
    sheet.getRange(2, i+2).setValue(item);
  }

  var regexp_temperature = /<tr class="temperature">([\s\S]*?)<\/tr>/i;
  var match_temperature = regexp_temperature.exec(tenki_table);
  var tenki_temperature = match_temperature[1];

  var tenki_temperature_arr = tenki_temperature.split("</td>");
  sheet.getRange(3, 1).setValue("気温");
  for(var i=0;i<tenki_temperature_arr.length;i++){
    var item = tenki_temperature_arr[i];
    item = delTag(item);
    item = trim(item);
    if(item == ""){
      continue;
    }
    sheet.getRange(3, i+2).setValue(Math.floor(item));
  }

  var regexp_precip = /<tr class="prob-precip">([\s\S]*?)<\/tr>/i;
  var match_precip = regexp_precip.exec(tenki_table);
  var tenki_precip = match_precip[1];

  var tenki_precip_arr = tenki_precip.split("</td>");
  sheet.getRange(4, 1).setValue("降水確率");
  for(var i=0;i<tenki_precip_arr.length;i++){
    var item = tenki_precip_arr[i];
    item = item.replace(/降水確率|\(\%\)/g, '');
    item = delTag(item);
    item = trim(item);
    sheet.getRange(4, i+2).setValue(item);
  }

  var msg = "今日の天気をお知らせします。";

  var asa_weather = sheet.getRange(2, 3).getValue();
  var asa_temperature = sheet.getRange(3, 3).getValue();
  var asa_precip = sheet.getRange(4, 3).getValue();

  msg += "朝の天気は、" + asa_weather + "。";
  msg += "気温は、" + asa_temperature + "度。";
  msg += "降水確率、" + asa_precip + "パーセント。";

  var hiru_weather = sheet.getRange(2, 5).getValue();
  var hiru_temperature = sheet.getRange(3, 5).getValue();
  var hiru_precip = sheet.getRange(4, 5).getValue();

  msg += "昼の天気は、" + hiru_weather + "。";
  msg += "気温は、" + hiru_temperature + "度。";
  msg += "降水確率、" + hiru_precip + "パーセント。";

  var yoru_weather = sheet.getRange(2, 7).getValue();
  var yoru_temperature = sheet.getRange(3, 7).getValue();
  var yoru_precip = sheet.getRange(4, 7).getValue();

  msg += "夜の天気は、" + yoru_weather + "。";
  msg += "気温は、" + yoru_temperature + "度。";
  msg += "降水確率、" + yoru_precip + "パーセント。";

  sheet.getRange(5, 1).setValue(msg); //デバッグ用

  Logger.log(msg); //今日の天気をお知らせします。朝の天気は、曇り。気温は、23度。降水確率、20パーセント。昼の天気は、小雨。気温は、24度。降水確率、60パーセント。夜の天気は、曇り。気温は、22度。降水確率、50パーセント。
}

function trim(str){
  return str.replace(/(^\s+)|(\s+$)/g, "");
}

function delTag(str){ //tag削除
  return str.replace(/<("[^"]*"|'[^']*'|[^'">])*>/g,'');
}

こんな感じで、取得したデータをわかりやすく、スプレッドシートに表示してみました。

このスクリプトをタイマー設定して、最後に出てきたメッセージを Google Home に投げて、音声出力しています。

データの取得方法が、APIではなく、スクレイピングなので、tenki.jp のHTMLテンプレートが変われば、またそれに対応しないといけません。