【iCal】Googleカレンダーに日本気象協会10日間天気予報を表示する方法【コピペ】

Googleカレンダーで天気予報がいっしょに見られると、予定を立てるときに便利ですよね。

スプレッドシートとGoogleAppsScript(GAS)を使うと、簡単に毎日自動更新されるiCalファイルが作れます。

Googleカレンダーには天気予報を表示する機能があるそうなのですが、やり方がよく分かりませんでした。
気象庁の天気予報をiCalで配信している方もいらっしゃいますが、細かい市町村単位では無いので私には役に立ちませんでした。

というわけで、自分の住んでいる町をピンポイントで10日後までの天気予報を表示するiCalカレンダーを自前で作って使っていました。

折角なので今回はやり方を公開してみようと思いますが、日本気象協会の予報を取得するので、私的利用のみで2次利用出来ないことには注意してください。

気象業務法「第十七条」について

天気予報の公開は法律によって許可制度になっています。

(予報業務の許可)
第十七条 気象庁以外の者が気象、地象、津波、高潮、波浪又は洪水の予報の業務(以下「予報業務」という。)を行おうとする場合は、気象庁長官の許可を受けなければならない。
2 前項の許可は、予報業務の目的及び範囲を定めて行う。

https://www.jma.go.jp/jma/kishou/info/ml-17.html

許可が必要なのはどんな場合かというと、

許可が必要な気象等の予報業務とはどのようなものですか。
気温や天気などの気象等の要素について、観測資料などをもとに独自に科学的に予想した結果を他者に発表する業務を行う場合には、予報業務許可を取得する必要があります。
例えば、観測資料などにもとづき独自に予想した明日の天気をテレビやホームページなどで発表したり他の法人に提供したりするには予報業務許可が必要です。

気象庁の予報をテレビで解説する場合には予報業務許可が必要ですか。
気象庁の発表した予報や他の許可事業者が発表した予報を解説するだけであれば、予報業務許可は必要ありません。

http://www.jma.go.jp/jma/kishou/minkan/q_a_m.html

気象庁の発表した予報をもとに独自に予想をして勝手に公開することはできないということになります。

気象庁のコンテンツは出典を記載すれば自由に利用できますし、独自の予想をしないで公開するなら問題ないです。

また、日本気象協会のコンテンツは私的利用など以外の二次利用不可なことも付け加えておきます。

Q.画像やコンテンツの二次利用をしてもいいですか
原則、当サイトの画像やコンテンツなどの二次利用はお断りしております。
ただし、「tenki.jp」のロゴまたはクレジットが記載されているものについては、私的使用のための複製や、学校などの教育機関での利用など著作権法で認められている範囲内に限り、以下のルールに沿ってご利用いただけます。その際、当協会及び当社に許諾は不要です。

https://tenki.jp/docs/help/#a09-10

なので、このページで説明している方法は個人使用のみでお使い下さい。

Googleカレンダーに週間天気予報を表示するまでの手順(説明無し)

手順だけ分かればいい方のために、最初に手順をまとめて記載します。
スクリーンショットを含めた具体的な手順の説明は下の方に書いています。

まずは、Googleスプレッドシートでの作業

  1. スプレッドシートを新規作成する
  2. B1セルに日本気象協会10日間天気のURLをコピペする。
    例:

    https://tenki.jp/forecast/2/5/3110/2323/10days.html
  3. C2セルに以下をコピペします。
    =ARRAY_CONSTRAIN(importxml($B$1,"//*[@id='main-column']/section/table[1]/tbody/tr/th[1][contains(text(),'月')]/../th[3]/span[@class='high-temp']"),5,1)
  4. D2セルに以下をコピペします。
    =ARRAY_CONSTRAIN(importxml($B$1,"//*[@id='main-column']/section/table[1]/tbody/tr/th[1][contains(text(),'月')]/../th[3]/span[@class='low-temp']"),6,1)
  5. E2セルに以下をコピペします。
    =importxml($B$1,"//*[@id='main-column']/section/table[1]/tbody/tr/th[1][contains(text(),'月')]/..")
  6. A2セルに以下をコピペします。
    =if(today()>DATEVALUE(REGEXREPLACE(REGEXEXTRACT(E2,"[0-9]{1,2}月[0-9]{1,2}"),"[月]","-"))
    ,DATEVALUE(year(today())+1&"-"&REGEXREPLACE(REGEXEXTRACT(E2,"[0-9]{1,2}月[0-9]{1,2}"),"[月]","-"))
    ,DATEVALUE(year(today())&"-"&REGEXREPLACE(REGEXEXTRACT(E2,"[0-9]{1,2}月[0-9]{1,2}"),"[月]","-")))
  7. A2セルの右下をクリックしたまま下へ11セル分ドラッグしてセルをコピーします。
  8. B2セルに以下をコピペします。
    ="天気:"&F2&" 気温:"&C2&"/"&D2
  9. B2セルの右下をクリックしたまま下へ11セル分ドラッグしてセルをコピーします。
  10. C7セルに以下のコードをコピペします。
    =ARRAY_CONSTRAIN(importxml($B$1,"//*[@id='main-column']/section/table[2]/tbody/tr/th[1][contains(text(),'月')]/../th[3]/span[@class='high-temp']"),6,1)
  11. D7セルに以下のコードをコピペします。
    =ARRAY_CONSTRAIN(importxml($B$1,"//*[@id='main-column']/section/table[2]/tbody/tr/th[1][contains(text(),'月')]/../th[3]/span[@class='low-temp']"),6,1)
  12. E7セルに以下のコードをコピペします。
    =importxml($B$1,"//*[@id='main-column']/section/table[2]/tbody/tr/th[1][contains(text(),'月')]/..")
  13. スプレッドシートに名前をつけて終了。

次に、スクリプトエディタでの作業

  1. ツール – スクリプトエディタ を開く
  2. 以下のスクリプトをコピペ
    function doGet(e) {
      var ical=""
      ical += "BEGIN:VCALENDAR\n"
      ical += "VERSION:2.0\n"
      ical += "PRODID:ore\n"
      ical += "CALSCALE:GREGORIAN\n"
      ical += "METHOD:PUBLISH\n"
      ical += "X-WR-CALNAME:" + SpreadsheetApp.getActiveSpreadsheet().getName() + "\n"
      ical += "X-WR-CALDESC:" + SpreadsheetApp.getActiveSpreadsheet().getName() + "を表示します。端末によってはテキスト表示になります。\n"
      ical += "X-WR-TIMEZONE:Asia/Tokyo\n"
      ical += "BEGIN:VTIMEZONE\n"
      ical += "TZID:Asia/Tokyo\n"
      ical += "BEGIN:STANDARD\n"
      ical += "DTSTART:19700101T000000\n"
      ical += "TZOFFSETFROM:+0900\n"
      ical += "TZOFFSETTO:+0900\n"
      ical += "END:STANDARD\n"
      ical += "END:VTIMEZONE\n"
      var weatherdata = SpreadsheetApp.getActiveSheet()
      var rows = weatherdata.getDataRange().getValues()
      for (rowNum = 1; rowNum < rows.length; rowNum++) {
        var row = rows[rowNum]
        var formatedDate = Utilities.formatDate(row[0], "JST", "yyyyMMdd")
        
        ical += "BEGIN:VEVENT\n"
        ical += "DTSTART:" + formatedDate + "\n"
        ical += "DTEND:" + formatedDate + "\n"
        ical += "SUMMARY:" + row[1] + "\n"
        ical += "TRANSP:TRANSPARENT\n"
        ical += "END:VEVENT\n"
      }
      ical += "END:VCALENDAR"
      return ContentService.createTextOutput(ical)
    }
  3. 保存後、実行をクリックして、権限の設定もする
  4. ウェブアプリの新しいデプロイを作成する

最後に、Googleカレンダーでの作業

    1. 他のカレンダー – URLで追加でウェブアプリのURLを設定

日本気象協会の10日間天気予報から情報を取得する具体的な手順と説明

情報をまとめるGoogleスプレッドシートを作る

  • A列:日付(後で使いやすいように日付形式データで)
  • B列:Googleカレンダーで出力したい文字列
  • C列:最高気温
  • D列:最低気温
  • E列:日本気象協会10日間天気のtable内容(日時)
  • F列:日本気象協会10日間天気のtable内容(天気)
  • G列:日本気象協会10日間天気のtable内容(気温)
  • H列:日本気象協会10日間天気のtable内容(降水確率)
  • I列:日本気象協会10日間天気のtable内容(注意事項)

最終的にこのようにデータが揃うようにします。

日本気象協会のページから1個目のtableをスクレイピング

では、天気データを集めていきます。

まずは、知りたい天気予報のページを開きます。

説明は深浦町のページで進めます。
https://tenki.jp/forecast/2/5/3110/2323/10days.html

このページのソースコードを見ると、1個目のtableタグに今日を含めて5日分の天気予報がまとまっています。
このtableから情報を得ることにします。

10日間天気予報ページのURLをB1のセルに転記します

このセルにURLを入れておくことで、それぞれのデータを読み込む時に個別にURLを入力する必要がなくなります。

最高気温を読み込む

C2セルに以下の=ARRAY_CONSTRAIN文をコピペします。

=ARRAY_CONSTRAIN(importxml($B$1,"//*[@id='main-column']/section/table[1]/tbody/tr/th[1][contains(text(),'月')]/../th[3]/span[@class='high-temp']"),5,1)


読み込みが終了すると

この様に5日分の最高気温が表示されます。

B1のURLページにあるid=’main-column’要素のタグの中のsectionタグの中の最初のtableタグの中の・・・class=’high-temp’要素を読み込みます。
長いです・・・。

簡単に言うと、tableの日時の項目が「○月○日」となっている行だけを抜き出します。
画像の赤枠の行のことです。

その行にあるclass=’high-temp’が最高気温の文字列です。

最低気温を読み込む

最高気温と同じように最低気温も読み込みます。
D2セルに以下のコードをコピペします。

=ARRAY_CONSTRAIN(importxml($B$1,"//*[@id='main-column']/section/table[1]/tbody/tr/th[1][contains(text(),'月')]/../th[3]/span[@class='low-temp']"),6,1)

そうすると、5日分の最低気温が読み込まれます

天気などを読み込む

E2セルに以下のコードをコピペします。

=importxml($B$1,"//*[@id='main-column']/section/table[1]/tbody/tr/th[1][contains(text(),'月')]/..")

10日間天気のページにあるtableタグで、日時の項目が「○月○日」となっている行をまるまる全部抜き出すためのコードです。
1個目のtableタグ内には「○月○日」の行が5行あるので、それを全部読み込んでスプレッドシートに出力します。

スプレッドシートのA列のセルに日付形式でデータを保存する

A列とB列に素材を作ります。

日付はテキストよりも日付形式にしておいた方が後で楽なので、A列に日付形式で保存します。
日付はE列の文字列から作成します。

この時注意する点は、年末に12月31日・1月1日が出て来た時、1月1日は来年にしなければいけません。
普通に変換すると今年の1月1日になってしまいます。

そこはif文で分けて対処することにしました。
月日を使って日付データに変換した時に、今日(例えば2021年12月○日)より前の日付(例えば2021年1月○日)だった時は年に1を足す(2022年1月○日)ことにします。

=if(today()>DATEVALUE(REGEXREPLACE(REGEXEXTRACT(E2,"[0-9]{1,2}月[0-9]{1,2}"),"[月]","-"))
,DATEVALUE(year(today())+1&"-"&REGEXREPLACE(REGEXEXTRACT(E2,"[0-9]{1,2}月[0-9]{1,2}"),"[月]","-"))
,DATEVALUE(year(today())&"-"&REGEXREPLACE(REGEXEXTRACT(E2,"[0-9]{1,2}月[0-9]{1,2}"),"[月]","-")))

上記コードをA2セルにコピペして、セルの右下をクリックしたままA12まで下へドラッグしてセルをコピーします。

(すみません、画像はA13までになっていました。あとでエラーが出るので、A12までにしてください。)

これで、コード中のE2セル参照がE3、E4・・・とその行に合わせて変換されてコピーされます。

この時の値が日付形式になっていない時は、セル設定を変えましょう。

セルを選択して、123▼のボタンから日付を選択します。


するとこの様に、年月日になります。

スプレッドシートのB列セルにカレンダーで表示したい情報をまとめる

B列にカレンダーに表示したいテキストを作っておけば、iCalに変換するときに楽です。
後で変更するときもスプレッドシートを書き換えるだけで、スクリプトには手を付けずに変更出来ます。

私は、天気と最高気温と最低気温を表示したいので、以下のようにB2セルに入力しました。
降水確率も必要な方は改変してください。

="天気:"&F2&" 気温:"&C2&"/"&D2

これで、

天気:雨のち曇 気温:25℃/21℃

のように表示されます。

B2セルの右下角をクリックしてB12までなぞってコピーします。
(画像はB11まででした。すみません、B12までなぞってください。)

日本気象協会のページから2個目のtableをスクレイピング

6日目から11日目の天気予報データは2個目のtableに書かれているので、1個目のtableからデータを取得したときと同様にします。

コピペのコードだけ書きますので、それぞれのセルにコピペ

最高気温を読み込む

C7セルに以下のコードをコピペします。

=ARRAY_CONSTRAIN(importxml($B$1,"//*[@id='main-column']/section/table[2]/tbody/tr/th[1][contains(text(),'月')]/../th[3]/span[@class='high-temp']"),6,1)

最低気温を読み込む

D7セルに以下のコードをコピペします。

=ARRAY_CONSTRAIN(importxml($B$1,"//*[@id='main-column']/section/table[2]/tbody/tr/th[1][contains(text(),'月')]/../th[3]/span[@class='low-temp']"),6,1)

天気などを読み込む

E7セルに以下のコードをコピペします。

=importxml($B$1,"//*[@id='main-column']/section/table[2]/tbody/tr/th[1][contains(text(),'月')]/..")

スプレッドシートのA列のセルに日付形式でデータを保存する

ここはもう11セル分コピーしているはずなので、やることはありません。

スプレッドシートのB列セルにカレンダーで表示したい情報をまとめる

こちらも、もう11セル分コピーしているはずなので、やることはありません。

スプレッドシートの名前を付ける

スプレッドシートに名前を付けてスプレッドシートでの作業は終了です。
お疲れ様でした。

次にスクリプトエディタの作業に移ります。

スクリプトエディタを開く


スプレッドシートのツールにあるスクリプトエディタをクリックします。

するとこの様なプログラムを書くページになります。

スクリプトエディタにコードをコピペする

すでに書かれているfunction myFanction(){}を全部削除して、以下のプログラムをコピペします。

function doGet(e) {
  var ical=""
  ical += "BEGIN:VCALENDAR\n"
  ical += "VERSION:2.0\n"
  ical += "PRODID:ore\n"
  ical += "CALSCALE:GREGORIAN\n"
  ical += "METHOD:PUBLISH\n"
  ical += "X-WR-CALNAME:" + SpreadsheetApp.getActiveSpreadsheet().getName() + "\n"
  ical += "X-WR-CALDESC:" + SpreadsheetApp.getActiveSpreadsheet().getName() + "を表示します。端末によってはテキスト表示になります。\n"
  ical += "X-WR-TIMEZONE:Asia/Tokyo\n"
  ical += "BEGIN:VTIMEZONE\n"
  ical += "TZID:Asia/Tokyo\n"
  ical += "BEGIN:STANDARD\n"
  ical += "DTSTART:19700101T000000\n"
  ical += "TZOFFSETFROM:+0900\n"
  ical += "TZOFFSETTO:+0900\n"
  ical += "END:STANDARD\n"
  ical += "END:VTIMEZONE\n"
  var weatherdata = SpreadsheetApp.getActiveSheet()
  var rows = weatherdata.getDataRange().getValues()
  for (rowNum = 1; rowNum < rows.length; rowNum++) {
    var row = rows[rowNum]
    var formatedDate = Utilities.formatDate(row[0], "JST", "yyyyMMdd")
    
    ical += "BEGIN:VEVENT\n"
    ical += "DTSTART:" + formatedDate + "\n"
    ical += "DTEND:" + formatedDate + "\n"
    ical += "SUMMARY:" + row[1] + "\n"
    ical += "TRANSP:TRANSPARENT\n"
    ical += "END:VEVENT\n"
  }
  ical += "END:VCALENDAR"
  return ContentService.createTextOutput(ical)
}

スプレッドシートの値を参照してiCalの要素に当てはめて出力するプログラムになります。

iCalの仕様も分かりづらくて調べるのが大変でしたが、これで動くのでよしとします。

WEBアプリとして呼び出すには、doGet(e)関数が呼び出されるので、function doGet(e)でiCalを出力するようにします。

外部から呼び出せるようにデプロイ設定する

コピペが終わったら、フロッピーディスクマークのボタンで保存します。

次に「実行」をクリックします。

すると、Googleアカウントの承認の手続きが出るので進めます。

「このアプリはGoogleで確認されていません」という表示が出るので、下の「詳細」をクリックします。

一番下の「無題のプロジェクトに移動」をクリック

許可しますか?と出るので、「許可」をクリックします。

エラーが無ければ実行完了と下の実行ログに表示されます。

実行完了と表示されないで、画面が止まった時は上に「停止」のボタンがあるので、それをクリック。
スプレッドシートに問題があります。
エラー表示が出たときもスプレッドシートの修正が必要です。

おそらく、A列の日付が書いている所で、A13以下に日付以外の文字列があることが原因だと思います。
それらを削除してください。

デプロイする



新しいデプロイで、ウェブアプリを作ります。
赤枠の所をそれぞれ、「自分」・「全員」に設定してデプロイします。

ウェブアプリのURLが生成されるので、コピーしておきます。

GoogleカレンダーでiCalを読み込む

そして、最後にGoogleカレンダーにカレンダーを登録します。

GoogleカレンダーにiCal形式ファイルをURLで追加

Googleカレンダーを開きます。

左側にあるリストから他のカレンダーの「+」ボタンをクリックして、URLで追加します。

これで、Googleカレンダーの終日予定に10日後までの天気予報が表示されます。

まとめ

このシステムは、一度作ると定期的にGoogleカレンダーがiCalを呼び出し、スプレッドシートが更新されて、毎日自動更新される天気予報システムになります。


投稿日

カテゴリー:

投稿者:

タグ:

コメント

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA