旅する医用工学者

医用工学に関するトピックを中心に,臨床工学技士国家試験,第1種ME技術実力検定試験,第2種ME技術実力検定試験に関係する内容についても取り扱います.日々の技術開発や受験勉強や学校の授業の予習・復習にお役立てください.内容の正確性には留意していますが,これを保証するものではありません.

M5Stamp C3U + MicroPython による気象庁天気予報データのスクレイピング

M5Stamp C3Uで遊んでみよう!

前回の記事でWindow + MicropythonでM5Stamp C3Uを開発する環境構築について紹介した。

medicalengineer.hatenablog.jpしかし、Lチカをしただけでは芸がない。何か役に立つモノを作ってみたくなるのが人情ではないだろうか。M5Stamp C3UはWiFi接続も可能なデバイスであるため、Webから何かのデータを持ってきて表示するのも面白そうだ。よし、早速天気予報でもスクレイピングしてみよう。

 

天気予報のスクレイピング

Web上で天気予報を確認する方も多いだろうが、国内の天気予報サイトの代表格といえば気象庁のサイトではなかろうか。

気象庁による東京地方の天気予報のページ

気象庁の天気予報ページは、jsonとよばれるデータ記述言語で記載されたデータを参照して自動的に生成されている。

東京都の天気予報を表示するためのjson

 

なお、このjsonデータの読み方については、気象庁防災情報XMLフォーマット情報提供ページに詳細が掲載されている。

xml.kishou.go.jp気象庁の天気予報ページが参照しているjsonファイルの中で用いられている"areas"や"weatherCodes"等の項目の対応に関しては、"電文毎の解説資料(令和4年7月28日一部更新)"に収録されている"府県天気予報・府県週間天気予報_解説資料付録.xls"に掲載されている。

https://xml.kishou.go.jp/jmaxml_20220728_Manual(pdf).zip

今回は、この資料を参考に、気象庁jsonのデータを読み取って、M5Stamp C3Uに接続した小型ディスプレイに表示してみよう。

 

スクレイピングの準備

スクレイピングの準備として、予報対象地域のコードを確認しよう。例えば、東京都の天気予報のページのURLは、

"https://www.jma.go.jp/bosai/#pattern=forecast&area_type=offices&area_code=130000"

であるが、"area_code"の後に続く6桁の数字が各都道府県に対応している。すなわち、東京都のコードは130000だ。ただし、エリアの広い北海道、鹿児島、沖縄の各道県は道県単位ではなく、地方単位(例えば、北海道ならば宗谷、上川・留萌、網走・北見・紋別……)での対応となる。上記ページから都道府県・地方を選択するメニュー画面を出し、対象の都道府県(以上3道県は地方)の天気予報を表示する。

都道府県・地方の選択メニュー

 

対称の都道府県の天気予報を表示したら、そのURLから"area_code"を確認する。例えば、北海道宗谷地方のURLは

"https://www.jma.go.jp/bosai/#pattern=forecast&area_type=offices&area_code=011000"

であるので、コードは011000だということがわかる。これでスクレイピングの準備は完了だ。

 

パッケージのインストール

続いてThonnyを用いて必要なパッケージをインストールする。今回作成するプログラムでは、SSD1306を制御するための"micropython-ssd1306"と、Webデータを取得するための"micropython-urequest"という2つのパッケージを利用するので、それらをインストールしよう。

Thonny上で"Tools"→"Manage packages"とクリックすると、マイコンにインストールされているパッケージの管理画面が表示される。検索ウィンドウに"micropython-ssd-1306"と入力して、"Search on PyPI"をクリックして検索する。

mycropython-ssd1306ライブラリのインストール

"micropython-ssd1306"を選択し、"Install"をクリックしてインストールする。

mycropython-ssd1306ライブラリのインストール

同様に"micropython-urequest"も検索してインストールする。2つのパッケージのインストールが完了したら、"Close"をクリックしてウィンドウを閉じておく。

 

配線

さて、早速回路を組み立ててゆこう。今回の作例であれば、M5Stamp C3Uのほか、128×32pixelのOLEDディスプレイ、ジャンパ線4本(接続を工夫すれば減らすことも可能)、ブレッドボードが必要だ。

配線は極めて単純で、M5Stamp C3UにSSD1306 OLEDディスプレイをI2C接続するだけだ。OLEDのVCCはM5Stamp C3Uの任意の5Vピン、GNDは任意のGNDピンに接続すればよく、SCLとSDAはプログラム上で指定すればよい。今回は、SCLは4番ピン、SDAは3番ピンを使うこととした。

配線

コーディング

配線が済んだらコーディングだ。Thonnyで以下のコードを入力(もしくはCopy & Paste)する。ただし、"your_ssid"はWiFiSSID、"your_password"はWiFiのパスワードを入力し、"https://www.jma.go.jp/bosai/forecast/data/forecast/130000.json"の"130000"部分は対象の都道府県(北海道、鹿児島、沖縄の3道県は地方)のコードを入力する。さらに、都道府県内の地域の選択は"areas"の引数(0, 1, 2,...)を変更してやればよい。

# -*- coding:utf-8 -*-

import machine
from machine import Pin, SoftI2C
import ssd1306
import urequests as requests
import json
import network

ssid = "your_ssid"
password = "your_password"

wlan = network.WLAN(network.STA_IF)
wlan.active(True)
if not wlan.isconnected():
    print('connecting to network...')
    wlan.connect(ssid, password)
    while not wlan.isconnected():
        pass
print("WiFi Connected")

i2c = SoftI2C(scl = Pin(4), sda = Pin(3))
display = ssd1306.SSD1306_I2C(128,32,i2c)

def decodeWeather(weatherCodes):
    if weatherCodes in [100,123,124,130,131]:
        weather = "Sunny"
    elif weatherCodes in [101,132]:
        weather = "Sunny / Cloudy"
    elif weatherCodes in [102,103,106,107,108,120,121,140]:
        weather = "Sunny / Rainy"
    elif weatherCodes in [104,105,160,170]:
        weather = "Sunny / Snowy"
    elif weatherCodes in [110,111]:
        weather = "Sunny > Cloudy"
    elif weatherCodes in [112,113,114,118,119,122,125,126,127,128]:
        weather = "Sunny > Rainy"
    elif weatherCodes in [115,116,117,181]:
        weather = "Sunny > Snowy"
    elif weatherCodes in [200,203,206,207,208,220,221,240]:
        weather = "Cloudy"
    elif weatherCodes in [201,223]:
        weather = "Cloudy / Sunny"
    elif weatherCodes in [202,203,206,207,208,220,221,240]:
        weather = "Cloudy / Rainy"
    elif weatherCodes in [204,205,250,260,270]:
        weather = "Cloudy / Snowy"
    elif weatherCodes in [210,211]:
        weather = "Cloudy > Sunny"
    elif weatherCodes in [212,213,214,218,219,222,224,225,226]:
        weather = "Cloudy > Rainy"
    elif weatherCodes in [215,216,217,228,229,230,281]:
        weather = "Cloudy > Snowy"
    elif weatherCodes in [300,304,306,328,329,350]:
        weather = "Rainy"
    elif weatherCodes in [301]:
        weather = "Rainy / Sunny"
    elif weatherCodes in [302]:
        weather = "Rainy / Cloudy"
    elif weatherCodes in [303,309,322]:
        weather = "Rainy / Snowy"
    elif weatherCodes in [308]:
        weather = "Rainstorm"
    elif weatherCodes in [311,316,320,323,324,325]:
        weather = "Rainy > Sunny"
    elif weatherCodes in [313,317,321]:
        weather = "Rainy > Cloudy"
    elif weatherCodes in [314,315,326,327]:
        weather = "Rainy > Snowy"
    elif weatherCodes in [340,400,405,425,426,427,450]:
        weather = "Snowy"
    elif weatherCodes in [401]:
        weather = "Snowy / Sunny"
    elif weatherCodes in [402]:
        weather = "Snowy / Cloudy"
    elif weatherCodes in [403,409]:
        weather = "Snowy / Rainy"
    elif weatherCodes in [406,409]:
        weather = "Snowstorm"
    elif weatherCodes in [361,411,420]:
        weather = "Snowy > Sunny"
    elif weatherCodes in [371,413,421]:
        weather = "Snowy > Cloudy"
    elif weatherCodes in [414,422,423]:
        weather = "Snowy > Rainy"
    else:
        weather = "Unknown"
    return weather

jma_url = "https://www.jma.go.jp/bosai/forecast/data/forecast/130000.json"
jma_json = requests.get(jma_url).json()
jma_date = jma_json[0]["timeSeries"][0]["timeDefines"][0]
jma_weather = jma_json[0]["timeSeries"][0]["areas"][0]["weathers"][0]
jma_weatherCodes = int(jma_json[0]["timeSeries"][0]["areas"][0]["weatherCodes"][0])

today_date = jma_date[0:10]
today_date = today_date.replace("-","/")
jma_weather = jma_weather.replace(" ", "")
today_weather = decodeWeather(jma_weatherCodes)

print(jma_date)
print(jma_weather)
print(jma_weatherCodes)

display.text(today_date,0,0,1)
display.text(today_weather,0,16,1)
display.show()

Thonnyによるコーディング

コーディングが済んだら、"File"→"Save as"とクリックし、"MicroPython device"を選択し、"main.py"というファイル名を指定して保存する。

保存した後、F5キーを押すか、"Run current script"をクリックすれば書き込んだプログラムが実行され、ディスプレイには日付と天気予報が表示されている筈だ。

 

動作確認


また、ThonnyのShellには上記コードのprint文の内容が表示されている筈だ。スタンドアロンで動作させるときはShellの内容は確認できないのだが、万一うまく動作しないようであれば、このShellの内容をもとにデバッグすることとなるため、要所要所でShellにメッセージを出力させるような設計にしておくとよい。

print命令の内容はShellに表示される

以上、M5StampとMycroPythonを用いたWebスクレイピングを試してみた。慣れれば半日かからずに完成できるため、小学生から高校生の皆さんの夏休みの自由研究にもちょうどいいかもしれない。