概要
気象庁のデータをGASで取得し、対象地域の翌日の降水確率が50%以上なら、LINE公式アカウント(旧LINE@)で雨の日セールを投稿する。といった流れ。
経緯
今年4月にLINEのMessaging APIに触る機会があり、それ以降沼にハマってしまい、色々試しているうちにLINE公式アカウントの利用者が面倒であろう販促投稿を自動で出来ないか検証。興味をもってくれた方がいたので、"雨の日セール"の自動投稿の仕組みをつくってみることに。
使用したもの
・LINE Messaging API
・Google Apps Script (GAS)
・気象庁ホームページ
気象データの取得について
天気の情報 = OpenWeatherMap と思いつつ、いろいろ調べているうちに、どうやら気象庁のデータがJSONで取得できるようになったみたいなので、そちらを試してみることに。
一番伸びてるのはこれかしら。仕様の継続性や運用状況のお知らせを気象庁はお約束していないという意味で、APIではないと申し上げざるを得ないのですが、一方で政府標準利用規約に準拠してご利用いただけます。 https://t.co/QLuhI4DNDv
— TOYODA Eizi (@e_toyoda) February 24, 2021
気象庁データのJSON取得
まずはデータを取得するURLを調べてみる。
https://www.jma.go.jp/bosai/forecast/data/forecast/(area_code).json
(area_code)の所に取得したい地域のコードを入れるとjsonでデータが表示される。
各地域のコード … 気象庁 天気予報より都道府県を指定し遷移後のURL末端にある6ケタの数字
データを取得する方法がわかったので、GASで当該のデータを取得してみる。(下コードは山口県の気象データを取得)
const response = UrlFetchApp.fetch(`https://www.jma.go.jp/bosai/forecast/data/forecast/350000.json`)
const data = JSON.parse(response)
降水確率50%以上の判定
元データのサイトを見ると、複数の地域の降水確率があるので今回はピンポイントに中部のデータのみ対象。
上記で取得したデータのうち中部の降水確率はここに格納されている。
data[0].timeSeries[1].areas[1].pops
しかし取得する時間によって格納される値の数が変動する(今日の過ぎた時間帯の値は入らない)ので、発表された時刻を指定(今回は17時発表を採用)することに。
var date = new Date();
var datetime = Utilities.formatDate(date, 'Asia/Tokyo', 'yyyy-MM-dd') + 'T17:00:00+09:00';
if(datetime != data[0].reportDatetime) return;
本題の判定へ。
3つの時間帯でそれぞれ降水確率が50%以上なら値を格納。(夜の時間帯は判定から除外するため、すでに値が入っている場合のみ格納。)
/*中略*/
var rainy_msg = rainychk(data[0].timeSeries[1].areas[1].pops,'50')
// 値が入っていれば投稿処理へ
function rainychk(rainyArray, value){
var msg = ''
var rainymsg = ''
var i = rainyArray.length - 1
// valueの値以上になったらメッセージ文を代入
// 夜の時間帯は営業時間から外れるため判定から除外
if(rainyArray[i-3] >= value) rainymsg += ' 朝:' + rainyArray[i-3] + '%'
if(rainyArray[i-2] >= value) rainymsg += ' 昼前:' + rainyArray[i-2] + '%'
if(rainyArray[i-1] >= value) rainymsg += ' 昼間:' + rainyArray[i-1] + '%'
if((rainyArray[i] >= value)&&(rainymsg != "")) rainymsg += ' 夜:' + rainyArray[i] + '%'
if(rainymsg != '') msg = '降水確率は' + rainymsg + ' になっています。'
return msg;
}
LINE公式アカウントへ投稿
上記の判定処理を通したのち投稿処理へ
/*中略*/
var tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
var tomorrowformat = Utilities.formatDate(tomorrow, 'Asia/Tokyo', 'M/d');
var title = '【明日は雨の予報☂ 限定クーポン配信】';
var header = 'こんばんは\uDBC0\uDC02\n\n'
var footer = '\n\nお出かけの際はお気をつけ下さいませ。\n\n↓雨の日限定クーポンお知らせ↓'
var msg = title + '\n\n' + header + '明日' + tomorrowformat + 'の山口は雨の予報です☂\n' + rainy_msg + footer;
var imageURL = '販促画像リンク';
var postData = {
'messages': [{
'type': 'text',
'text': msg
},{
"type": "flex",
"altText": title,
"contents": {
"type": "bubble",
"hero": {
"type": "image",
"url": imageURL,
"size": "full",
"aspectRatio": "1:1.035",
"aspectMode": "cover"
}
}
}],
};
broadcast_fetch_data(postData);
function broadcast_fetch_data(postData) {
var options = {
"method": "post",
"headers": {
"Content-Type": "application/json",
"Authorization": "Bearer " + "LINEのアクセストークン"
},
"payload": JSON.stringify(postData)
};
UrlFetchApp.fetch("https://api.line.me/v2/bot/message/broadcast", options);
}
あとはGASのトリガーで毎日一定時間に作動させれば無事完了。
備考
今回作った仕組みを動かしてみて約1ヶ月。今のところ目立った不具合はないものの、はっきりとしたAPIとはいえないので、若干様子をみつつ不都合が発生した場合にOpenWeatherMapのデータも取得するような2重構造を考え中。
あとはJSON内にweatherCodesというものを使って簡潔な天気(晴れ、曇、雨のち晴れなど)が取れないか試したものの、まだまだ把握できないコードがいくつか出てきたので今回は採用を見送り。 誰かまとめてくれないかなぁ