本記事ではSlackbotで天気を表示する方法について説明します。
天気情報は気象予報サイトが提供している天気データを活用することで表示可能です。
PythonやJavaScriptを活用すれば簡単にSlackbotに組み込むことができます。
天気予報の表示手順はWebサイトのデータを利用した他の処理にも応用することができるので仕組みを理解しておきましょう。
本記事の内容は以下の通り。
・Web APIから天気を取得する方法
・Python+Slackbotで天気情報を取得する方法
・JavaScript(Node.js)+Botkitで天気情報を取得する方法
Pythonに加えてJavaScriptでの実装方法についても紹介します。
簡単な処理で実装できるので本記事を参考にしつつ作成してみてください。
目次
Web APIから天気を取得する方法
天気情報の取得は「livedoor天気情報」が非常に便利だったのですが、サービスが終了してしまいました。
公式:■サービス終了のお知らせ
今回は、ライブドアの天気情報と似た方法で使える有志の方が作成してくれたAPIを活用します。
APIご利用の際は下記ページをよく読んだ上でご活用ください。
天気予報 API(livedoor 天気互換)
上記サイトよりJSONデータと呼ばれるデータを取得します。
URLパラメータの「130010」には都市ごとに割り振られた番号を指定します。上記の例では東京都の番号「130010」を指定しています。
都市ごとに割り振られた番号は「全国の地点定義表 」から確認できます。
都市ごとに、
のように定義されています。idの部分が都市ごとに割り振られた番号です。
Python+slackbotで天気情報を取得する方法
天気情報を取得するためにはURLからJSONファイルをダウンロードしてテキストデータとして変換する必要があります。
天気情報取得のコードは以下の通りです。
◆サンプルコード
miyabikno/slackbot-py
import json
# URLアクセスを制御するためのライブラリを読み込む
import requests# URL情報を変数に格納する
url = "https://weather.tsukumijima.net/api/forecast/city/130010"
# URLアクセスして情報を取得する
response = requests.get(url)
# URL取得に失敗した場合の例外処理を行うメソッド
response.raise_for_status()
# 取得したjsonデータをテキストとして読み込む
weather_data = json.loads(response.text)
天気の情報は取得したJSONファイルの「'forecasts'」に格納されています。
今日の情報を取得する場合はweather_data['forecasts'][0]のデータを参照します。
weather_data['forecasts'][0]の内容は以下の通りです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | { 'dateLabel': '今日', 'telop': '晴れ', 'date': '2018-12-19', 'temperature': { 'min': None, 'max': { 'celsius': '14', 'fahrenheit': '57.2' } }, 'image': { 'width': 50, 'url': 'http://weather.livedoor.com/img/icon/1.gif', 'title': '晴れ', 'height': 31 } }, |
なお、weather_data['forecasts'][1]には明日の天気が格納されています。
実装方法と実行例
今回は以下のファイルを修正します。
・weather.py:天気管理用ファイル(新規ファイル)
・botmodule.py:Botモジュールの定義ファイル
PythonでのSlackbot作成の基本については「SlackbotをPythonで作成しよう」をお読みください。
・weather.py:天気を取得するモジュールを定義する
天気情報を読み込むためのモジュールを定義します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | # ライブラリの読み込み import json import requests # 天気情報を取得するための関数 def get_weather(city_number): url = "https://weather.tsukumijima.net/api/forecast/city/%s" % city_number # URLアクセスして情報を取得する response = requests.get(url) response.raise_for_status() # 取得したjsonデータを読み込む weather_data = json.loads(response.text) return(weather_data) |
・botmodule.pyの修正
今日の天気を返答する処理をBotに追記します。
天気情報は「weather_data['forecasts'][0]['telop']」を参照しましょう。
1 2 3 4 5 6 7 8 | # 作成した天気情報モジュールを読み込む import weather @respond_to('今日の天気') def whether_1(message): w = weather.get_weather(130010) t = w['forecasts'][0] message.reply(t['telop']) |
応答バリエーションの追加
上記は単純に天気をメッセージとして表示するだけでしたが、以下ではメッセージのバリエーションを増やす方法を紹介します。
◆メッセージに天気の絵文字を追加する
天気の絵文字を加える方法です。
辞書型の天気情報を用意しておき、それを元に絵文字に置き換えます。
def whether_1(message):
# 絵文字リストを作る
dic_weather = {
'晴れ' : 'sunny',
'曇り' : 'cloud',
'雨' : 'rain_cloud',
'雪' : 'snow_cloud'
}
w = weather.get_weather(130010)
t = w['forecasts'][0] telop = t['telop'] # 絵文字情報を取得する
emoji = ':' + dic_weather[telop] + ':'
message.reply('今日の天気は%sです%s' % (telop, emoji))
上記の例では、4種類しか天気は定義していません。「晴れ時々曇り」などイレギュラーなものが来るとエラーとなってしまいます。
定義を追加していく方法もありますが、イレギュラーなものが来ても動くようにしておきましょう。
以下、修正を加えたコードです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | @respond_to('^(今日|明日|明後日)の天気$') def whether_1(message, group): # 絵文字リストを作る dic_weather = { '晴れ': 'sunny', '曇り': 'cloud', '雨': 'rain_cloud', '雪': 'snow_cloud', '曇時々晴': 'barely_sunny', } dic_date = { '今日': 0, '明日': 1, } w = weather.get_weather(130010) t = w['forecasts'][dic_date[group]] telop = t['telop'] # 辞書にない天気が来たら絵文字に空文字を設定する if telop in dic_weather: emoji = ':' + dic_weather[telop] + ':' else: emoji = "" message.reply('%sの天気は%sです%s' % (group, telop, emoji)) |
◆天気をリアクションで返す
応答する代わりに天気をリアクションとして返すことも可能です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | @respond_to('今日の天気') def whether_2(message): # 絵文字リストを作る dic_weather = { '晴れ' : 'sunny', '曇り' : 'cloud', '雨' : 'rain_cloud', '雪' : 'snow_cloud', } w = weather.get_weather(130010) t = w['forecasts'][0] telop = t['telop'] # 絵文字情報を取得する if telop in dic_weather: emoji = dic_weather[telop] message.react(emoji) else: message.reply('絵文字を取得できませんでした。今日の天気は%sです' % telop) |
定義を追加します。
1 2 3 4 5 6 7 | dic_weather = { '晴れ' : 'sunny', '曇り' : 'cloud', '雨' : 'rain_cloud', '雪' : 'snow_cloud', '曇時々晴' : 'barely_sunny', } |
◆他の日の天気を表示する
当日だけではなく翌日の天気を表示することも可能です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | @respond_to('^(今日|明日)の天気$') def whether_1(message, group): # 絵文字リストを作る dic_weather = { '晴れ' : 'sunny', '曇り' : 'cloud', '雨' : 'rain_cloud', '雪' : 'snow_cloud', '曇時々晴' : 'barely_sunny', } dic_date = { '今日': 0, '明日': 1, '明後日': 2 } w = weather.get_weather(130010) t = w['forecasts'][dic_date[group]] telop = t['telop'] # 辞書にない天気が来たら絵文字に空文字を設定する if telop in dic_weather: emoji = ':' + dic_weather[telop] + ':' else: emoji = "" message.reply('今日の天気は%sです%s' % (telop, emoji)) |
JavaScript(Node.js)+Botkitで天気情報を取得する方法
JavaScript(Node.js) + Botkitでの実装方法について説明します。
JavaScriptでのSlackbotの作成については「SlackbotをJavaScriptで作成しよう」をお読みください。
JavaScript(Node.js)で天気を表示する方法
Node.jsもrequestライブラリで天気を読み込めます。
1 2 3 4 5 6 7 8 9 10 | var request = require('request'); var options = { url: 'https://weather.tsukumijima.net/api/forecast/city/130010', method: 'GET', json: true } request(options, function (error, response, body) { var t = body['forecasts'][0] }) |
上記処理を「controller.hears()」内に組み込めばOKです。
実装例と実行例
実装例と実行例は以下の通りです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | // APIトークンを指定する var api_token = process.env.BOT_API_TOKEN if (!api_token) { console.log('Error: Specify token in environment'); process.exit(1); } var Botkit = require('botkit/lib/Botkit.js'); var os = require('os'); var request = require('request'); var controller = Botkit.slackbot({ debug: true, }); var bot = controller.spawn({ token: api_token }).startRTM(); controller.hears(['天気'], 'mention, direct_mention', function(bot, message) { var options = { url: 'http://weather.livedoor.com/forecast/webservice/json/v1?city=130010', method: 'GET', json: true } # 非同期処理なのでrequest内で処理を行う必要がある request(options, function (error, response, body) { var t = body['forecasts'][0] bot_reply(message, '今日の天気は' + t['telop'] + 'です') }) }); # Botの応答関数 function bot_reply(message, text) { controller.storage.users.get(message.user, function(err, user) { bot.reply(message, text); }); } |
以上、Slackbotで天気情報を応答させる方法でした。
気象サイトのデータを活用する処理は他のWebデータを活用する処理にも応用ができます。
Webサイトをデータの使い方について仕組みを理解しておきましょう。
◆サンプルコード(Python)
miyabikno/slackbot-py
※リファクタリングや不具合の修正などで記事と内容が異なっている場合があります。
SlackbotまとめTOP>>Slackbotの作り方マニュアル〜Python編〜
関連記事>>SlackのRSSを活用して天気予報やブログ記事を定期購読する