電車が遅延・運休したらLINEに通知するスクリプトを書いてみた

# 背景
私自身が列車通勤なので、通勤用のライフハック用として作ってみました。
通勤前・退勤前に列車止まってるのがわかるのと駅行ってから止まってるのがわかるのとでは精神的なダメージが全然違いますしね・・・


# 事前に用意するもの
・Linuxサーバ（cron使います。RaspberryPiでも可です）
・python3
・Beautifulsoup
・LineNotify

# しくみ
今回は下記サイト(鉄道運行情報)から列車の運行情報を抽出します。
ここでは常磐線（関東エリア）のページを例にとって説明。
http://www.jikokuhyo.co.jp/search/detail/line_is/kanto_joban

上記URLのHTMLを見ると、
46〜47行目に運行情報が格納されているのがわかります。
本スクリプトではここの部分を抽出します。

```
<div class="corner_block_row_detail_d" style="padding-left:5px;"> 
 現在、平常通り運転しています。</div> 
```

上記のサイトから運行情報を取得したい線区のURLを指定しても良いですが
今回は、複数の線区の情報をまとめて取得してみようと思います。

まずは２つのtxtを作成。
前者が運行情報を取得したい線区名を記載したファイル（SENKU_DB.txt)
後者が取得したい線区名の運行情報のURLを記載したファイル（URL_DB.txt）です。

SENKU_DB.txtとURL_DB.txtで記載されている線区名、URLはそれぞれ1対1で紐付いていることを前提とします。

```SENKU_DB.txt
【中央線快速電車(東京〜高尾)】
【中央・総武各駅停車(三鷹〜千葉)】
【中央本線(高尾〜小淵沢)
【山手線】
【京浜東北線(大宮〜大船)】
【横須賀線(東京〜久里浜)】
【総武快速線(東京〜千葉)】
【東海道線(東京〜熱海)】
【常磐線(品川〜いわき)】
【常磐線快速電車(品川〜取手)】
【常磐線各駅電車(綾瀬〜取手)】
【宇都宮線(東京〜黒磯)】
【高崎線(東京〜高崎)】
【上野東京ライン】
【湘南新宿ライン】
【埼京線(大崎〜大宮)】
【南武線(川崎〜立川)】
【武蔵野線(府中本町〜西船橋)】
【青梅線(立川〜奥多摩)】
【五日市線(拝島〜武蔵五日市)】
【横浜線(東神奈川〜八王子)】
【京葉線(東京〜蘇我)】
```

```URL_DB.txt
http://www.jikokuhyo.co.jp/search/detail/line_is/kanto_chuokaisoku
http://www.jikokuhyo.co.jp/search/detail/line_is/kanto_chuosobu
http://www.jikokuhyo.co.jp/search/detail/line_is/kanto_chuo
http://www.jikokuhyo.co.jp/search/detail/line_is/kanto_yamanote
http://www.jikokuhyo.co.jp/search/detail/line_is/kanto_keihintohoku
http://www.jikokuhyo.co.jp/search/detail/line_is/kanto_yokosuka
http://www.jikokuhyo.co.jp/search/detail/line_is/kanto_sobukaisoku
http://www.jikokuhyo.co.jp/search/detail/line_is/kanto_tokaido
http://www.jikokuhyo.co.jp/search/detail/line_is/kanto_joban
http://www.jikokuhyo.co.jp/search/detail/line_is/kanto_jobankaisoku
http://www.jikokuhyo.co.jp/search/detail/line_is/kanto_jobankakueki
http://www.jikokuhyo.co.jp/search/detail/line_is/kanto_utsunomiya
http://www.jikokuhyo.co.jp/search/detail/line_is/kanto_takasaki
http://www.jikokuhyo.co.jp/search/detail/line_is/kanto_uenotokyo
http://www.jikokuhyo.co.jp/search/detail/line_is/kanto_shonanshinjuku
http://www.jikokuhyo.co.jp/search/detail/line_is/kanto_saikyo
http://www.jikokuhyo.co.jp/search/detail/line_is/kanto_nambu
http://www.jikokuhyo.co.jp/search/detail/line_is/kanto_musashino
http://www.jikokuhyo.co.jp/search/detail/line_is/kanto_ome
http://www.jikokuhyo.co.jp/search/detail/line_is/kanto_itsukaichi
http://www.jikokuhyo.co.jp/search/detail/line_is/kanto_yokohama
http://www.jikokuhyo.co.jp/search/detail/line_is/kanto_keiyo
```

鋭い方はもうお気づきかもしれませんが、今回作成するスクリプトは
<font color=red><b>これらのtxtファイルに書かれている線区の運行情報をスクレイピングし、電車の運休・遅延どのキーワードがあったら、LINEで通知する</font></b>といったものになります。
LINEへの通知はLine NotifyのAPIを使用します。
詳細は過去に書いた記事を参照ください。

◆【2019/4/7更新】LINE Notify + Pythonで天気情報を取得する方法
https://qiita.com/S_eki/items/206ddb321768ad4e7544


# 実装したスクリプト
では、LINE通知のトリガーになっている運休・遅延のキーワードをどうやって判別するか。
鉄道運行情報のサイトのHTMLをみたところ、通常運行中に出てくる情報は下記の２つであることがわかりました。

<font color=blue>・現在、平常通り運転しています。
・情報提供時間は4：00～翌2：00となっています。</font>

上記２点以外の情報が出たら、通知という条件ならうまくいきそう。

早速実装してみました。

```GetTrainInfo.py
from bs4 import BeautifulSoup as bs4
import urllib.request as ur
import re
import requests

# Read DB
senku_data = open("SENKU_DB.txt", "r")
url_data = open("URL_DB.txt", "r")

# Make DB SENKU List & URL List
SENKU_DB = senku_data.readlines()
URL_DB = url_data.readlines()

# Set Line Notify token and API
line_notify_token = 'INPUT YOUR TOKEN ID'
line_notify_api = 'https://notify-api.line.me/api/notify'

# Import Senku Data and URL from the beginning
for target_senku, url in zip(SENKU_DB, URL_DB):
    req = ur.urlopen(url)
    html = bs4(req, "html.parser")
    match = html.find(class_="corner_block_row_detail_d").string.replace('\n','')
    text = target_senku + '\n ' + match
            
    # Export only delay or cancel train information by using LINE Notify
    if (match != '現在、平常通り運転しています。' and match != '情報提供時間は4：00～翌2：00となっています。'):
        message = '\n' + text
        payload = {'message': message}
        headers = {'Authorization': 'Bearer ' + line_notify_token}
        line_notify = requests.post(line_notify_api, data=payload, headers=headers)

# Close DB
senku_data.close()
url_data.close()

```

処理の流れを簡単にまとめると下記の通り。
<b>1)それぞれのtxtファイルに記載されている線区、URLを一行ずつ切り出してリスト化。
2)リスト化したURLからforループで１つずつ読み取り、運行情報をスクレイピング。
3)抽出した運行情報が<font color=blue>上記青字</font>以外のものだったらLINENotify経由で通知。</b>



あとは手持ちのサーバ上でcron設定。
１時間に１〜２回起動するようにしておけば良いと思います。

```
0 */1 * * * cd /home/pi/Ryo/tools/GetTrainInfo; python3 GetTrainInfo.py
```

#実行結果
こんな感じで出てきます。

![EDYfSTwU8AAHjSC.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197189/f9c18bb2-9634-66ae-b718-406790ee25ac.jpeg)

#使用上の注意点
- 上記の"GetTrainInfo.py"は、"SENKU_DB.txt"と"URL_DB.txt"が同じ階層に格納されていることが前提で実装しています。 txtファイルを別の場所に格納したい場合は、7〜8Stepのopen関数で読み込んでいるtxtファイルを絶対パスで入力してください。
- データ収集等が目的でない限り、"SENKU_DB.txt"と"URL_DB.txt"に記載する線区とURLは最小限にしておくことを推奨します。大量に記載すると、台風が来てダイヤが乱れたときに大量の通知が来ます。