ITmedia NEWS > STUDIO >
連載
» 2021年11月23日 07時00分 公開

電車の運行情報を通知LEDでチェックする名刺サイズの超小型PC「ラズパイ」で遊ぶ(第49回)

「Yahoo!路線情報」から情報を取り出して、状況をLEDで分かるようにしてみます。

[岩泉茂,ITmedia]

 新型コロナウイルス感染症(COVID‑19)の影響でテレワークが広がり、週の半分以上は自宅で仕事をしている人も多いと思います。そんな中でたまにある出勤日、うっかり何も確認せずに家を出てしまって「電車が遅延していた」「もっと早く家を出ればよかった……」ということもあるかもしれません。これを防ぐために、ラズパイを使って簡単に路線情報を表示してくれる仕組みを作ってみることにします。

 具体的には「Yahoo!路線情報」から情報を取り出し、赤、黄色、緑のLEDを使って、「緑であれば異常なし」「黄色であれば遅延あり」「赤はその他(事故、運休など)」と、状況によって点灯するようにしましょう。なお、この構成は「ツール・ラボ」さんのページを参考にしています。

 まずはYahoo!路線情報のHTMLデータを確認してみましょう。在来線の場合、データは北海道、東北、関東、中部、近畿中国、四国、九州のエリアに分かれて掲載されています。今回はまず関東のデータについて扱うことにします。

 まずはwgetコマンドでindex.htmlをダウンロードしましょう。

$ wget "https://transit.yahoo.co.jp/traininfo/area/4/"

 ダウンロードしたindex.htmlのソースをテキストエディタなどで見ると、以下のように構成されていることに気付きます。

<tr>
<td><a href="https://transit.yahoo.co.jp/traininfo/detail/21/0/">山手線</a></td>
<td>平常運転</td>
<td>事故・遅延情報はありません</td>
</tr>
<tr>
<td><a href="https://transit.yahoo.co.jp/traininfo/detail/22/0/">京浜東北根岸線</a></td>
<td>平常運転</td>
<td>事故・遅延情報はありません</td>
</tr>
<tr>
<td><a href="https://transit.yahoo.co.jp/traininfo/detail/25/0/">湘南新宿ライン</a></td>
<td>平常運転</td>
<td>事故・遅延情報はありません</td>
</tr>
<tr>
<td><a href="https://transit.yahoo.co.jp/traininfo/detail/27/0/">東海道本線[東京〜熱海]</a></td>
<td>平常運転</td>
<td>事故・遅延情報はありません</td>
</tr>
……

 分かりましたでしょうか。路線名のあとに[]があり、その次の行で「平常運転」などの情報が書かれています。こちらに着目して作ることにしましょう。

 まずは情報を取得する路線を「rosenname」とし、読み込んだindex.htmlファイルを「rosendata」で1行ずつ格納します。どのようなな内容となっているのかを分かりやすいようにprint文で追ってみましょう。以下のプロフラムを「train01.py」などと保存して実行してみてください。なお路線名はYahoo!路線情報に書いてある通りに入力します。

#!/usr/bin/python
# coding: utf-8
import urllib.request
# 情報を取得する路線名
rosenname = '山手線'
 
# Yahoo! Japan運行情報ページ(関東)のURL
url = "https://transit.yahoo.co.jp/traininfo/area/4/"
# Yahoo! Japan運行情報ページのHTMLデータ取得して1行ずつリストに格納
response = urllib.request.urlopen(url)
htmldata = response.read().decode("utf-8")
train01.py

 保存したら以下のコマンドで実行します。

$ python3 train01.py

 実行するとindex.htmlの内容が“だーっ”と流れたかと思います。これでデータを取得できていることが分かります。

 続いてこのHTMLソースをデータとして格納する仕組みを作ります。データはrosendataに格納します。以下のプログラムを「train02.py」などと保存して実行してみましょう。

#!/usr/bin/python
# coding: utf-8
 
import urllib.request
# 情報を取得する路線名
rosenname = '山手線'
# Yahoo! Japan運行情報ページ
url = "https://transit.yahoo.co.jp/traininfo/area/4/"
 
# HTMLデータを1行ずつリストに格納
response = urllib.request.urlopen(url)
htmldata = response.read().decode("utf-8")
rosendata = htmldata.splitlines()
print(rosendata)
train02.py

 保存したら以下のコマンドで実行します。

$ python3 train02.py

 今度は違う形でソースが流れたかと思います。このプログラムではそれぞれの行をrosendataに格納していますが、改行ごとにカンマ区切りで構成されているため、このようになります。

 ではいよいよ、路線の情報からLEDの点灯までの仕組みを作り上げましょう。先ほども述べたとおり、路線名の次の行に「平常」、「遅延」といったデータがありますので、if文で条件を分岐させてLEDを点灯させます。プログラムは以下のようになります。なおコメント文にも書いていますが、今のところはテストなので、先ほどwgetでダウンロードしたHTMLファイルを参照するように設定しています。

 まずLEDですが、市販のLED3色を用意してもよいのですが、信号機っぽいLEDをAmazonで見つけましたので、これを使うことにしました。抵抗が内蔵されているようで、別途抵抗を用意しなくても、直接ラズパイにつなげて使えます。LEDですが、gpiozeroでコントロールすることにします。LEDの「GND」をラズパイのGNDにつなげ、「R」をGPIO18に、「Y」をGPIO15に、「G」をGPIO14につないでいます。

Raspberry pi ラズパイとLEDの接続

 接続が終わったらLEDがちゃんと接続されているかテストしましょう。以下のプログラムを実行してみてください。

#!/usr/bin/python
# coding: utf-8
from gpiozero import LED
from time import sleep
green=LED(14)
yellow=LED(15)
red=LED(18)
try:
    while True:
        green.on()
        print("Blue is on")
        sleep(1)
        
        yellow.on()
        print("Yellow is on")
        sleep(1)
        
        red.on()
        print("Red is on")
        sleep(1)
        green.off()
        yellow.off()
        red.off()
        print("LED off")
        sleep(1)
except KeyboardInterrupt:
    print("End")
lchika.py

 保存したら以下のコマンドで実行します。

$ python lchika.py

 実行すると緑、黄色、赤の順にLEDが点灯し、そのあとすべてオフになります。

 では本題のプログラムに戻りましょう。以下の内容を「train03.py」として保存し、実行してください。

#!/usr/bin/python
# coding: utf-8
 
import urllib.request
from gpiozero import LED
from time import sleep
# LEDのGPIO番号
green=LED(14)
yellow=LED(15)
red=LED(18)
# 情報を取得する路線名
rosenname = '山手線'
# Yahoo! Japan運行情報ページ
url = "https://transit.yahoo.co.jp/traininfo/area/4/"
 
# テスト用HTMLからデータを取得
f = open('./index.html')
htmldata = f.read()
f.close()
rosendata = htmldata.splitlines()
for i in range(0, len(rosendata)):
    # 路線名の文字列があるか確認
    pos = rosendata[i].find(rosenname+'</a></td>')
    if pos >= 0:
        # 「平常」が含まれるか確認
        pos = rosendata[i+1].find('平常')
        if pos >= 0:
            # 平常運転であれば緑が点灯
            green.on()
            sleep(1)
    
        else:
            # 「遅延」が含まれるか確認
            pos = rosendata[i+1].find('遅延')
            if pos >= 0:
                # 遅延であれば黄色が点滅
                yellow.on()
                sleep(0.5)
                yellow.off()
                sleep(0.5)
            else:
                # 平常運転、遅延でもなければ赤色を点灯して警告
                red.on()
train03.py

 保存したら以下のコマンドで実行します。

$ python train02.py

 いかがでしょうか。「平常運転」であれば緑、「遅延」があれば黄色、その他の場合は赤のLEDが点灯するかと思います。今はテストなので、今回指定した山手線について、index.htmlの内容を「遅延」あるいは「事故」などに変えて、ちゃんと動くのか確かめておいた方がよいでしょう。

 では本番のプログラムに移ります。テスト用に設定したHTMLファイルではなく、実際にYahoo! 路線情報からデータを取得するようにします。その方法としてはいくつか考えられますが、ここでは10分おきにデータを採るように設定しました。While True文で無限ループさせ、データを取得します。データの取得には「urllib」を使います。

#!/usr/bin/python
# coding: utf-8
 
import urllib.request
from gpiozero import LED
from time import sleep
# LEDのGPIO番号
green=LED(14)
yellow=LED(15)
red=LED(18)
# 情報を取得する路線名
rosenname = '山手線'
 
# Yahoo! Japan運行情報ページのURL
# 以下は関東地方の運行情報URL
url = "https://transit.yahoo.co.jp/traininfo/area/4/"
 
while True:
    # HTMLデータを1行ずつリストに格納
    response = urllib.request.urlopen(url)
    htmldata = response.read().decode("utf-8")
    rosendata = htmldata.splitlines()
    for i in range(0, len(rosendata)):
        # 路線名の文字列があるか確認
        pos = rosendata[i].find(rosenname+'</a></td>')
        if pos >= 0:
            # 「平常」が含まれるか確認
            pos = rosendata[i+1].find('平常')
            if pos >= 0:
                # 平常運転であれば緑が点灯
                green.on()
                sleep(1)
    
            else:
                # 「遅延」が含まれるか確認
                pos = rosendata[i+1].find('遅延')
                if pos >= 0:
                    # 遅延であれば黄色が点滅
                    yellow.on()
                    sleep(0.5)
                    yellow.off()
                    sleep(0.5)
                else:
                    # 平常運転、遅延でもなければ赤色を点灯して警告
                    red.on()
    # 更新する間隔
    sleep(600)
train.py

 保存したら以下のコマンドで実行します。

$ python train.py

 これで10分おきに取得したデータに基づいて遅延などの情報を示してくれます。今回は関東地方のデータでしたが、ほかの地域についてもURLと路線名を設定すれば取得できますので、自分のほしいデータに応じて加工してみてください。

 ただしその際は、1秒おきなど細かく時間を指定すると、サーバに負担をかけることになりますので、十分な時間を持って設定することを心掛けてください。

Copyright © ITmedia, Inc. All Rights Reserved.