Pythonロボティクスコース レッスン 43

テーマ.11-2 インターネットを利用した気象予報データの取得

インターネットのWebサイトから情報を取得しよう

このレッスンで学ぶこと

このレッスンでは、「世界気象機関(World Meteorological Organization:WMO)」から配信されている世界の気象予報のデータを取得して、Studuino:bitのLEDディスプレイに表示するプログラムを作成します。

HTTPのPOSTメソッド

前回のレッスンでは、HTTPの仕組みやHTTPで扱うメソッドについて紹介し、実際にGETメソッドを使用してインターネットから情報を取得する練習を行いました。ここでは、GETメソッドと並んでよく使用される「POSTメソッド」を実践してみましょう。

2. 1 GETメソッドとPOSTメソッドの違い

HTTPのGETメソッドとPOSTメソッドは、それぞれ以下の目的で使うことを説明しました。

  • GET
    リソースを取得するメソッド。GETメソッドを実行することで、サーバーのリソースが変更されることはありません。
  • POST
    データを送信するメソッド。サーバーは受信したデータを元に、リソースを書き換えたり、新たなリソースを作成したりして、レスポンスを送ります。

基本はGETメソッドはサーバーからのリソース取得、POSTメソッドはサーバーへのデータ送信を行うときに使われます。ただし、GETメソッドでもURLにクエリパラメータを含めることで、サーバーへデータを送信できました。

【 クエリパラメータを含んだURLの例 】
※ 末尾にある?以降のcolor=redがクエリパラメータ
https://www.artec-kk.co.jp/school/cl/textbooks/sample/getrgb.php?color=red

POSTメソッドを利用する代表例は、Webサイトのフォームデータの送信です。

送信するフォームデータは、リクエストのボディに含まれています。

サーバーはPOSTメソッドでリクエストが送られてきた場合はボディを確認し、その内容に合わせてリソースを更新したり、新たなWebページを作成してクライアントへレスポンスを返します。

2. 2 POSTメソッドの実践

では実際に、POSTメソッドを使ってサーバーにデータを送信してみましょう。練習用にWebサイトのログインフォームをイメージした以下のサンプルページを用意しています。

https://www.artec-kk.co.jp/school/cl/textbooks/sample/post

このページをそのままブラウザで開くと、次のメッセージが表示されます。

これはGETメソッドでリクエストを送っているためです。このページへはPOSTメソッドでidpasswordの2つのパラメータを送る必要があります。

前のレッスンで作成したWi-Fi接続用のモジュール(mywifi)とurequestsモジュールを使ってリクエストを送信し、そのレスポンスを表示するプログラムを作成しましょう。

■ プログラムの作成手順

始めにStuduino:bitをWi-Fiに接続します。前のレッスンを思い出しながら、以下のコードを書きましょう。

POSTメソッドでリクエストを送るときは、urequestsモジュールのpost()関数を使います。

urequests.post(url, data=None, header={})

GETメソッドでリクエストを送ったときは、リクエストのボディ(data)とヘッダ(header)を指定しませんでしたが、今回はそれらが必要になります。

まず、ボディには次の形式で送信したいデータを設定します。

id=....&password=....

この形式はクエリパラメータと同様で「変数名=値」でデータを表し、複数のパラメータがあるときは「&」でつなぎます。

ヘッダではボディのデータ形式をContent-Typeヘッダで示します。もしこれがなければ、リクエストを受け取ったサーバーは、送られてきたデータをどのように解釈すれば良いのか分かりません。

Content-Type: application/x-www-form-urlencoded

application/x-www-form-urlencodedは、変数名と値が間にある=で組み合わされており、情報が複数ある場合は&で区切られていることを示しています。フォームに入力したデータを送信するときは、基本的にこのヘッダ情報が指定されます。

これらのことを踏まえた上で以下のコードを追加して、レスポンスの内容をターミナルに表示しましょう。

【 サンプルコード 2-2-1 】
追加【13行目~16行目】

リクエストを送るWebページの認証に必要なIDとパスワードの組み合わせは次の通りです。

  • ID:python
  • パスワード:robotics

完成したプログラムを実行して、login()関数を呼び出してみましょう。

(正しいIDとパスワードの組み合わせを送信したときの結果)
(誤ったIDとパスワードの組み合わせを送信したときの結果)

このように受け取ったデータに応じて、サーバーは異なるレスポンスを返すようになっています。今回利用したWebページでは簡単なメッセージだけを返すようにしていましたが、実際のフォームでは入力されたメールアドレス宛てに受け付け確認メールを送信したり、フォームの情報をデータベースに登録したりする処理が行われています。

JSON(データ形式)

サーバーから返されるレスポンスのデータは、先ほどのような単純なテキストだけでなく、HTMLの文書やJavaScriptというWebブラウザで動作するプログラム言語で書かれたプログラムファイル、画像、音声、動画など様々です。

ここでは、その中から後の気象予報のデータ取得でも利用する「JSON(ジェイソン)」というデータについて紹介します。

3. 1 JSONとは

JSONは「JavaScript Object Notation」の略で、元々はJavaScriptというプログラム言語で扱うオブジェクトをテキスト形式で表現するために開発されたデータフォーマットの1種です。今ではWebのアプリケーションどうしでデータをやり取りするときの標準的なフォーマットのひとつとして使われています。

■ JSONのフォーマット

JSONのフォーマットは次の通りです。Pythonでいう複数の辞書型のデータが入れ子になった構造をしています。そのため、JSONはPythonでも簡単に扱うことができます。

{
    "data1": "string1",
    "data2": 2,
    "data3": {
        "data3_1": 3,
        "data3_2": "string3",
    }
}

3. 2 JSONの実践

それでは実際に以下のWebページからJSONのデータを取得してみましょう。

https://www.artec-kk.co.jp/school/cl/textbooks/sample/json

このページにWebブラウザでアクセスすると以下のようなJSONのデータが表示されます。

{"method":"show","args":{"string":"JSON","delay":400,"wait":false,"loop":false,"clear":true,"color":2031616}}

このままでは構造が分かりにくいので、整列してみましょう。

{
    "method": "show",
    "args": {
        "string": "JSON",
        "delay": 400,
        "wait": false,
        "loop": false,
        "clear": true,
        "color": 2031616
    }
}

実は、これらの情報はStuduino:bitのLEDディスプレイの制御方法を示していて、各パラメータは以下の情報を表しています。

パラメータ内容
"method"LEDディスプレイの制御メソッドの名前。リクエストを送るごとに"show"または"scrollのいずれかがランダムに選ばれます。
"args""method"に合わせた以下の引数情報。
【 “method”: “scroll” の場合の”args”のパラメータ 】
パラメータ内容
"string"scroll()メソッドの第1引数に対応。”JSON”で固定。
"delay"scroll()メソッドのdelay引数に対応。10で固定。
"wait"scroll()メソッドのwait引数に対応。falseで固定。
"loop"scroll()メソッドのloop引数に対応。falseで固定。
"color"scroll()メソッドのcolor引数に対応。7色からランダムに選ばれる。
【 “method”: “show” の場合の”args”のパラメータ 】
パラメータ内容
"string"show()メソッドの第1引数に対応。”JSON”で固定。
"delay"show()メソッドのdelay引数に対応。400で固定。
"wait"show()メソッドのwait引数に対応。falseで固定。
"loop"show()メソッドのloop引数に対応。falseで固定。
"clear"show()メソッドのclear引数に対応。trueで固定。
"color"show()メソッドのcolor引数に対応。7色からランダムに選ばれる。

いくつかのパラメータは、サーバー側で値がランダムに選択されるようになっています。

それでは取得したJSONデータの内容に合わせて、LEDディスプレイを制御するプログラムを作成してみましょう。

■ プログラムの作成手順

Studuino:bitをWi-Fiに接続するコードを書きます。

今回は送信するデータがないので、GETメソッドでリクエストを送ります。サーバーから送られてきたデータは、urequestsモジュールのget()メソッドで返されるresponseオブジェクトのcontentプロパティに格納されています。そして、responseオブジェクトがもつjson()メソッドを実行すると、contentがJSONとして解釈されて辞書型のデータが得られます。

以下のようにコードを追加して、ここまでのプログラムを実行してみましょう。

追加【6行目、13行目~16行目】
(実行結果の例)

一番下の行を見ると、<class 'dict'>が出力されていて、JSONのデータが辞書型のデータに変換できていることが分かります。

では、このデータを使ってLEDディスプレイを制御するコードを書きましょう。

【 サンプルコード 3-2-1 】
追加【18行目~32行目】

これでプログラムの完成です。ターミナルからcontrol_display()関数を呼び出すたびに、「JSON」の4文字がランダムな色でLEDディスプレイに表示されることを確認しましょう。

気象予報データの取得

政府機関や公益性のある機関のWebサイトでは、地域の人口の推移や人口における年齢比率、交通情報、災害情報、郵便番号、気象予報など様々な情報が無料で公開されています。

レッスンの後半では、国際連合の専門機関のひとつでもある「世界気象機関(World Meteorological Organization:通称WMO)」のWebサイトで公開されている加盟国の気象予報データを取得して、LEDディスプレイに結果を表示するプログラムを作成します。

【 世界気象機関 (World Meteorological Organization)とは 】
国際連合の専門機関の一つで、気象事業の国際的な標準化と改善および調整、
並びに各加盟国・地域間における気象情報・資料の効率的な交換の奨励を主な業務としている。
本部はスイスのジュネーヴにあり、国連開発グループ(UNDG)の一員である。
(引用:wkipedia「世界気象機関」)

4. 1 気象予報データの取得方法

WMOの加盟国の気象データの取得方法については、以下のページ(英語)にまとめられています。

https://worldweather.wmo.int/en/dataguide.html

このページに沿って手順を説明すると、最初に以下のURLにGETメソッドでリクエストを送ります。

https://worldweather.wmo.int/en/json/[City ID]_en.json

このURL内の[City ID]には、各国の都市に割り当てられている固有の番号を入力します。各都市の番号は以下のページで確認することができます。

https://worldweather.wmo.int/en/json/full_city_list.txt

例えば日本の場合は、以下の7都市が登録されていて、それぞれ次の[City ID]が割り当てられています。

【 日本の各都市の”City ID” 】
都市名[City ID]
札幌("Sapporo"181
仙台("Sendai"182
東京("Tokyo"183
名古屋("Nagoya"355
大阪("Osaka"184
福岡("Fukuoka"185
那覇("Naha"186

リクエストを送ると、JSONでまとめられた気象予報に関するデータが返ってきます。このデータは入れ子構造をもつ辞書型のオブジェクトを表していて、一番上の階層にcityという名前のキーがあります。

{
    "city":{}
}
キー名内容データ型
"city"対象地域の気象予報データ辞書型のオブジェクト

"city"の値も辞書型のオブジェクトになっていて、複数のキーを持っています。

【 “city”の内容例 】
    "city":{
        "lang":"en",
        "cityName":"Tokyo",
        "cityLatitude":"35.680000000",
        "cityLongitude":"139.770000000",
        "cityId":183,
        "isCapital":true,
        "stationName":"Tokyo",
        "tourismURL":"www.jnto.go.jp",
        "tourismBoardName":"Japan National Tourist Organization",
        "isDep":false,
        "timeZone":"+0900",
        "isDST":"N",
        "member":{},
        "forecast":{},
        "climate":{}
    }
キー名内容データ型
"lang"言語文字列
"cityName"都市名文字列
"cityLatitude"緯度文字列
"citiLongitude"経度文字列
"cityId"都市のID整数
"isCapital"首都かどうかブール値
"station Name"駅名、空港名文字列
"tourismURL"観光局のURL文字列
"tourismBoardName"観光局名文字列
"isDep"政治的に完全に独立していない地域かどうかブール値
"timeZone"タイムゾーン文字列
"isDST"都市がサマータイムにあるかどうか文字列
"member"世界気象機関の組織メンバーとしての情報辞書型のオブジェクト
"forecast"気象予報のデータ辞書型のオブジェクト
"climate"気候に関するデータ辞書型のオブジェクト

"member""forecast""climate"の値も辞書型のオブジェクトです。例えば"forecast"は次のキーを持っています。

【 “forecast”の内容例 】
        "forecast":{
            "issueDate":"2020-07-28 11:00:00",
            "timeZone":"Local",
            "forecastDay":[]
        }
キー名内容データ型
"issueDate"交付日時文字列
"timeZone"表示されている日付のタイムゾーン文字列
"forecastDay"気象予報の全データリスト型のオブジェクト

"forecastDay"はリスト型のオブジェクトになっており、[0]~[6]に明日以降の1週間分の気象予報データが格納されています。そして、このリストの各要素は以下のキーを中に含んでいます。

※ 取得する時間が早い場合、取得した日から1週間分の気象予報データが格納されています。
【 “forecastDay”の内容例 】
            "forecastDay":[
                {
                    "forecastDate":"2020-07-29",
                    "wxdesc":"",
                    "weather":"Rain",
                    "minTemp":"24",
                    "maxTemp":"27",
                    "minTempF":"75",
                    "maxTempF":"81",
                    "weatherIcon":1401
                },
                .
                .
                .
            ]
キー名内容データ型
"forecastDate"予報日文字列
"wxdesc"詳細に記述された気象情報文字列
"weather"気象文字列
"minTemp"最低気温(セ氏温度)数値(小数点以下あり)
"maxTemp"最高気温(セ氏温度)数値(小数点以下あり)
"minTempF"最低気温(華氏温度)数値(小数点以下あり)
"maxTempF"最高気温(華氏温度)数値(小数点以下あり)
"weatherIcon"気象に関するアイコンを表す番号/アイコンの一覧表はこちら整数値

今回は利用しませんが、"member""climate"の内容についても詳しく知りたい場合は、このJSONフォーマットを説明している以下のページ(英語)を参照してください。

http://worldweather.wmo.int/en/json/WWIS_json_schema_v2.json

以上のことから、例えば明日の気象を知りたい場合は、"city" ⇒ "forecast" ⇒ "forecastDay" ⇒ [0] ⇒ "weather" とキーを辿れば良いということになります。

という訳で、"weather"を確認すれば気象が分かりますが、実は気象を表す単語はかなりの数があります。以下の表はその一例です。

【 気象を表す単語の一例 】
気象名(英語)気象名(日本語)表す天気の様子
Sandstorm砂嵐激しい風によって、塵(ちり)や砂が空中高く吹き上げられるもの
Duststorm砂塵嵐砂嵐と同じだが、吹き上げられる粒子がより細かい
Sand大気中に塵や砂が舞っている状態
Dust大気中に塵や砂が舞っている状態(Sandより粒子がより細かい)
Thunderstorms雷雨激しい雨や風を伴う雷や稲妻からなる嵐
Thundershowers雷雨Thunderstormsより短い時間で起きる雷雨
Storm暴風雨強い風を伴う雨
Lightning稲妻雷や雷によって発生する光
Hail積乱雲から降る直径5mm以上の氷の粒
Blowing Snow吹雪地表に積もった雪が強風で吹き上がる様
Blizzard猛吹雪極地方などで発生する激しい吹雪
Snowdrift雪の吹きだまり降った雪が堆積したもの
Snowstorm吹雪強風によって雪が激しく乱れ飛びながら降る様
Snow Showersにわか雪一時的に強く雪が降る様
Flurries小雪こまかに雪が降る様
Snow大気中の水蒸気から生成される氷の結晶が空から落下してくる天気
Heavy Snow豪雪雪による雪害のうち、程度の著しいもの
Snowfall降雪雪が降ってくる天気
Light Snow泡雪あわのように軽くてとけやすい雪
Showersにわか雨一時的に降る雨
Heavy Showers豪雨一時的に激しく雨が降る
Rainshowerしゅう雨降水強度が急に変化し、降り始めから降り止みが突然で、連続・集中せずに何度も間をおいて降るような雨
Occasional Showers時々雨一定の予報期間において降ったりやんだりする雨
Scattered Showersにわか雨一時的に降る雨
Isolated Showers局所的なにわか雨局所的かつ一時的に降る雨
Light Showersよわいにわか雨より降水強度の弱いにわか雨
Freezing Rain凍雨透明あるいは半透明の氷が雨のように降る
Rain上空の水蒸気が、高所で凝結し、水滴となって落ちてくる天気
Drizzle霧雨粒子の細かい雨
Light Rain小雨降水量の少ない雨
Fog細かい水滴が地面・水面近くに集まって煙のようにかかる現象
Mist靄(もや)霧と同様の減少だが霧よりも薄いものを指す
Smoke森林火災などの影響で煙が空気中にあることを指す
Haze煙霧乾いた微粒子が大気中に浮遊している現象
Overcast曇りCloudyよりも空一面がどんよりとした雲で覆われている様
Sunny Intervals晴れ間雨や曇りの間にときどき見える晴れ間
Clearing晴れ間雨や曇りの間にときどき見える晴れ間
Sunny Periods晴れ間雨や曇りの間にときどき見える晴れ間
Partly Cloudyときどき曇り晴れよりも曇りの時間が短い(2分の1未満)
Partly Brightときどき晴れ曇りよりも晴れの時間が短い(2分の1未満)
Mildのどかな気候のどかで穏やかな過ごしやすい天気
Cloudyくもり空が雲で覆われている様子
Mostly Cloudyほとんど曇りほとんどの時間空がクモで覆われている様子
Bright晴れよく晴れた様子
Sunny晴れ太陽の光が照っている様
Fine晴れ過ごしやすい天候
Fair快晴雲が非常に少なく晴れた日
Clear快晴雲ひとつ無いような晴れた日
Windy強風風が強い日
Squall激しい天候変化豪雨や雷雨などを伴う激しい天候の変化
Stormy暴風/暴雨雨を伴うような激しい強風
Freezing非常に寒い凍えるような寒さ
Volcanic Ash火山灰火山灰が降る

地域によっては滅多に使われない気象名もあるでしょう。もし、取得した気象名がどのような天気の様子を表しているのか分からないときは、上の表で確認しましょう。

4. 2 プログラムの作成

それでは、気象予報データを取得して、ターミナルに明日(時間によっては今日)の「気象」「最高気温」「最低気温」を表示するプログラムを作成してみましょう。

■ Wi-Fiへの接続

気象予報データを取得する処理はget_forecast()関数としてまとめます。同じ関数で様々な都市に対応できるように、都市を表す固有番号を引数として受け取ります。Wi-Fiに未接続の場合はこの関数の冒頭で接続するようにしておきましょう。

■ 気象予報データの取得

リクエストの送信先となるURLは、都市によって異なります。すべてのパターンを用意すると大変なので、以下のように共通のフォーマットをひとつ用意します。

"https://worldweather.wmo.int/en/json/[City ID]_en.json"

このフォーマットの[City ID]の部分だけを、get_forecast()関数で受け取った引数の番号で置き換えることでURLを作成します。

追加【6行目、13・14行目】

■ ターミナルへの結果の表示

responseオブジェクトのjson()メソッドでJSONデータを辞書型のオブジェクトに変換して、「都市名」「予報日(明日または今日)」「気象」「最高気温」「最低気温」の5つの情報を取り出します。そして、これら5つの情報を含むメッセージをターミナルに表示しましょう。

【 サンプルコード 4-2-1 】
追加【15行目~23行目】

■ プログラムの動作確認

完成したプログラムを実行する前に、気象予報データを取得したい都市を決めて(例えば自分の住んでいる都市もしくは一番近い都市など)、以下のページで固有番号を調べておきます。

https://worldweather.wmo.int/en/json/full_city_list.txt

プログラムを実行して、ターミナルでget_forecast()関数に調べた番号を渡して呼び出しましょう。

(プログラムの実行例)
※ 「183」は日本の東京(Tokyo)を表しています。

課題:気象を表すアイコンを作成してLEDディスプレイに表示する

【 サンプルコード 4-2-1 】では、取得した気象予報をターミナルに表示しました。この課題では、気象を表すアイコン(イメージ)を用意して、追加でLEDディスプレイに表示するようにプログラムを改造してみましょう。

5. 1 ヒント:気象を表すアイコンの定義

前のチャプターで気象を表す名前が数多くあることを紹介しました。すべての気象に対してアイコンを用意するのは大変ですので、気象を次の5種類に分類します。

分類気象名
晴れNo Rain, Fine, Sunny, Clear, Clearing, Bright”, Fair, Mild
Thunderstorms, Thundershowers, Storm, Showers, Heavy Showers, Rainshower, Occasional Showers, Scattered Showers, Isolated Showers, Light Showers, Freezing Rain, Rain, Drizzle, Light Rain, Squall
曇りCloudy, Partly Cloudy, Sunny Intervals, Mostly Cloudy, Partly Bright
Snow, Flurries, Heavy Snow, Snowfall, Light Snow, Blizzard, Blowing Snow, Hail, Snow Showers, Snowstorm, Snowdrift
その他Sandstorm, Volcanic Ash など

そして5分類に対して、それぞれ次のアイコンを設定しましょう。

5. 2 プログラムの作成手順

次の手順でプログラムを改造します。

■ 気象の分類の定義

始めに気象の分類を定義します。上の表で示した分類ごとに、気象名をまとめた集合を作成しましょう。その他の分類については、他の4分類以外と考えることができるので、集合を定義する必要はありません。

追加【10行目~20行目】

■ 気象を表すアイコンの定義

次に分類した各気象を表すアイコンを定義します。

追加【2行目、23行目~27行目】

■ 気象名からアイコンを返す関数の作成

引数に気象名を渡すと対応するアイコンのイメージを返す関数を用意します。

追加【29行目~40行目】

■ 気象を表すアイコンの表示

最後に、LEDディスプレイへ気象を表すアイコンを表示します。これでプログラムの完成です。プログラムを実行して動作を確認しましょう。

【 サンプルコード 5-2-1 】
追加【55行目、57行目】

おわりに

6. 1 このレッスンのまとめ

このレッスンでは、HTTPのPOSTメソッドを実践し、またWebのアプリケーション間で受け渡しされるデータのフォーマットとして広く採用されている「JSON」について新たに学習しました。

そして、学習の応用として世界気象機関(WMO)のWebサイトから世界の各都市の気象予報データを取得するプログラムを作成しました。

今回利用した世界気象機関だけでなく、他にも様々な公的機関や民間企業のWebサイトでもJSONの形式で様々なデータが提供されています。興味のある人はぜひどのようなデータが取得できるのか検索して調べてみてください。

6. 2 次回のレッスンについて

次回のレッスンでは、ネットワークを利用してコンピュータに正確な時刻を設定する「NTP(Network Time Protocol)」という通信プロトコルについて学習します。

TOP