11 min readPython
【未経験者必見】Pythonを使って天気予報をLine通知してみる
突然ですが、みなさんは毎日天気予報をみていますか? つい天気予報を観るのを忘れて、傘を置いてきてしまったなんてこともあるのではないでしょうか? 天気予報を知るために、Line通知する方法を説明して参ります。ぜひ最後までご参考ください。
執筆者 - おすすめの記事2選
用意するもの
- ローカルにてPython環境が叩ける状態であること(ターミナルにて
python -V
でバージョンが表示されていること) - pipが入っていない場合はpipを入れておく(Python 3.4以降では標準で入っている。参考)
- Lineを利用していること、Line利用開始時に設定した「Email address, Password」の設定を覚えていること
- 通知したいLineグループが存在する場合、Lineアプリからグループを作成しておくこと、またLine NotifyをLineグループ内に友達追加しておくこと
- コードを編集する、個人に合うエディタが使える状態であること(おすすめはVsCode)
アーキテクチャ
実行手順
上記のアーキテクチャを見ただけではわからない部分も多々あるかと思います。まずは以下の手順を踏まえて、ローカル環境(自身のパソコン)にて実装してみましょう。
ローカル環境上にファイルを置く
以下の作業は、私の方で実際に作成したコードを、自身のパソコンへファイルを置く作業になります。
- こちらのページに訪問ください。
- 緑の「Code」と書かれているボタンをクリックして、 「Download ZIP」をクリックください。
- ダウンロードしたZipファイルをドラック&ドロップを使って、デスクトップへファイル移動して下さい。
- Zipファイルを展開するために、デスクトップに置いた先ほどのファイルをダブルクリックして下さい。
Line Notifyの設定を行う
以下の作業は、Line通知するために必要な「トークン」を発行するために必要な工程になります。トークンを発行する理由としては、「様々なグループ、ユーザー間に対して、通知が送られないように必要な鍵を発行している」のだと考えてください。
- こちらのページに訪問する。
- 右上に存在する「Log in」 テキストリンクをクリックする。
- ラインのログイン時に必要な「Email address, Password」を入力する。
- ログインしたら右上の自分の名前をクリックして、「My Page」のテキストリンクをクリックする。
- 下の方へ行くと、「Generate token」の文字が確認できるので、そのボタンをクリックする。
- 「Please enter a token name to be displayed before each notification.」の箇所に、通知の際にどのようなテキストを埋め込みたいのか設定します。(デモ内では、「港区の天気」を通知するものですので、「港区の天気」を設定しております。)
- 「Select a chat to send notifications to.」の箇所では、通知したいグループ名を選択します。
- 「Generate token」をクリックします。
- 最後にトークンが表示されるので、忘れないようにメモしておいてください。
Python を実行してみる
最後に必要なパッケージ(Pythonを実行する際に汎用的に使われるコード群)をインストールして、Pythonを実行します。
- ターミナルを開いて、weather-masterのディレクトリへ移動します。(
cd
を利用する。) - ターミナル上で
pip install -r requirements.txt
と入力する。(weather-masterディレクトリ内にrequirements.txtファイルを用意していて、ファイルを実行するために必要なパッケージ情報を記載しています。その情報を元に自身のパソコン内へパッケージを格納しています。) - お好みのエディタを立ち上げます。
- getWeather.py ファイルを開いて、以下のコードを変更する。
- iconPath の値を絶対パス指定で同階層に存在するimgディレクトリを示すように入力する。(例: /Users/xxx/desktop/weather-master/img/ ターミナル上で
pwd
コマンドを実行すると現在のパスを確認できます。) - lineNotifyToken の値に先ほど控えておいたトークンの値を格納する。
- iconPath の値を絶対パス指定で同階層に存在するimgディレクトリを示すように入力する。(例: /Users/xxx/desktop/weather-master/img/ ターミナル上で
- 最後に
python getWeather.py
を実行すると、先ほど登録したLineグループ宛に天気情報が送信されます。
完成動画
よくわかるコード解説
以下のコードでは、
- Yahoo側がRSS配信にて提供している天気予報情報を呼び出し、取得する。
- 取得したデータの中からタイトル、説明文のみを切り出す。
- 配列に格納する。
を行っております。自身の住んでいる天気予報を表示したい場合には、こちらのページを参考にrssUrlのURLの値を変更してみてください。
1# parser : 天気情報WebページのHTMLタグから天気情報を抽出してパースするメソッド
2def parser(rssUrl):
3 with urllib.request.urlopen(rssUrl) as res:
4 xml = res.read()
5 soup = BeautifulSoup(xml, "html.parser")
6 for item in soup.find_all("item"):
7 title = item.find("title").string
8 description = item.find("description").string
9 if title.find(keyword) != -1:
10 titleList.append(title)
11 descList.append(description)
以下のコードでは、
- 先ほど取得した説明文情報を参照する。
- 説明文に適した、画像を探し出す。(例: 晴れの場合は、晴れの画像を選択する。)
- 合致する画像が存在する場合、該当する画像ファイルを添付してLine通知を行う。
- 画像が存在しない場合には、画像ファイルの添付を行わないでLine通知を行う。
操作を行っております。
画像ファイルの判定に関しては、isFind 定数をフラグとして捉え、もしも画像が見つかった場合には、True, 見つからない場合にはFalseを返却するようにしております。
for文にて条件分岐を格納している理由としては、重複コードをなくすための工夫になります。
1# ckWeather : 取得した天気情報とそれに応じた天気アイコンを出力するメソッド
2def ckWeather(detail):
3 isFind = False
4 for boolean, fileName in [
5 [detail.find("晴") != -1 and (detail.find("曇")) == -1 and (detail.find("雨")) == -1 and (detail.find("雪")) == -1, "sunny.png"],
6 [detail.find("晴一時曇") != -1 or (detail.find("晴のち曇")) != -1 or (detail.find("晴時々曇")) != -1, "sunnyToCloud.png"],
7 [detail.find("晴一時雨") != -1 or (detail.find("晴のち雨")) != -1 or (detail.find("晴時々雨")), "sunnyToRain.jpg"],
8 [detail.find("晴一時雪") != -1 or (detail.find("晴のち雪")) != -1 or (detail.find("晴時々雪")) != -1, "sunnyToSnow.jpg"],
9 [detail.find("曇") != -1 and (detail.find("晴")) == -1 and (detail.find("雨")) == -1 and (detail.find("雪")) == -1, "cloud.png"],
10 [detail.find("曇一時晴") != -1 or (detail.find("曇のち晴")) != -1 or (detail.find("曇時々晴")) != -1, "cloudToSunny.png"],
11 [detail.find("曇一時雨") != -1 or (detail.find("曇のち雨")) != -1 or (detail.find("曇時々雨")) != -1, "cloudToRain.png"],
12 [detail.find("曇一時雪") != -1 or (detail.find("曇のち雪")) != -1 or (detail.find("曇時々雪")) != -1, "cloudToSnow.jpg"],
13 [detail.find("雨") != -1 and (detail.find("晴")) == -1 and (detail.find("曇")) == -1 and (detail.find("雪")) == -1, "rain.png"],
14 [detail.find("雨一時晴") != -1 or (detail.find("雨のち晴")) != -1 or (detail.find("雨時々晴")) != -1, "rainToSunny.jpg"],
15 [detail.find("雨一時曇") != -1 or (detail.find("雨のち曇")) != -1 or (detail.find("雨時々曇")) != -1, "rainToCloud.png"],
16 [detail.find("雨一時雪") != -1 or (detail.find("雨のち雪")) != -1 or (detail.find("雨時々雪")) != -1, "rainToSnow.png"],
17 [detail.find("雪") != -1 and (detail.find("晴")) == -1 and (detail.find("雨")) == -1 and (detail.find("曇")) == -1, "snow.png"],
18 [detail.find("雪一時晴") != -1 or (detail.find("雪のち晴")) != -1 or (detail.find("雪時々晴")) != -1, "snowToSunny.jpg"],
19 [detail.find("雪一時曇") != -1 or (detail.find("雪のち曇")) != -1 or (detail.find("雪時々曇")) != -1, "snowToCloud.jpg"],
20 [detail.find("雪一時雨") != -1 or (detail.find("雪のち雨")) != -1 or (detail.find("雪時々雨")) != -1, "snowToRain.jpg"],
21 [detail.find("暴風雨") == -1, "typhon.png"],
22 [detail.find("暴風雪") == -1, "heavySnow.jpg"],
23 ]:
24 if boolean:
25 files = {'imageFile': open(iconPath + fileName, "rb")}
26 requests.post(lineNotifyApi, data=payload, headers=headers, files=files)
27 isFind = True
28 break
29
30 if not isFind:
31 requests.post(lineNotifyApi, data=payload, headers=headers)
今日のまとめ
- Line Notifyを使うことで、Lineへ手軽に通知したい情報を送信できる。
- 天気などのRSS情報を活用して、気軽に自分の欲しい情報が取得できる。
- pip コマンドを利用して、コードを動かすために必要なパッケージ管理を容易にでき、必要なパッケージをrequirements.txtファイルを用いて、installできる。
こんなことにもチャレンジしてみよう
- 天気以外にもRSS情報はたくさんあるので叩いてみよう。(newsweekjapan, musicman)
- 今回ファイルを実行することで天気情報を通知していましたが、情報が欲しいタイミングで来ないと不便です。CrontabやRaspberry Piなどを活用してみましょう。
- 通知する手段として、Line以外にも様々あります。よく利用する通知先に天気情報を伝えてみましょう。(例: Slack)