先日地下鉄の駅構内で東京公共交通オープンデータチャレンジのポスターを見かけました。電車やバス、飛行機の情報をオープンデータとして提供するのでアプリケーションを作って応募してくださいというもの。
コンテストに応募するかどうかはともかく、少し触ってみました。

飛行機の発着情報を取ってみる
とりあえず簡単に扱えそうなデータで何か作れないかなと考えた結果、習作として羽田と成田の航空機発着情報提供メールサービスを作ってみました。
メールタイトルに6桁のフライト番号を書いてメールを送ると、当日のその便の情報が返信されるというもの。
こんな感じのメールが返ってきます。
Open Data Challenge for Public Transportation in Tokyo
Flight Information Alpha-RELEASE
2017-12-19T08:29:42+09:00
Flight No. : NH0856/GA9352
From CGK to HND
Scheduled Time is 06:50
Status : Arrived
Estimated Time is 06:35
JSONデータを取得する
データは東京公共交通オープンデータチャレンジAPIというWeb APIで提供されるJSON形式のデータです。このAPIを利用するには利用者登録をして個別にアクセスキーを貰う必要があります。
使い方はOpenExchangeRates APIとだいたい同じ。rdf:typeと呼ばれるAPIのコマンド種別を表すものを含むエンドポイントというurlに対して?でパラメータを繋げてアクセスします。
パラメータは最低限アクセスキーが必要。他にPREDICATEというrdf:type毎に異なるプロパティ名を指定することでデータの絞り込みができます。パラメータが複数になるときは&マークで繋げます。
例えばキャセイパシフィックのCX0520のフライト情報を取りたければ、こんな風にcurlを使ってデータをダウンロードします。
#! /bin/sh
ENDPOINT="https://api-tokyochallenge.odpt.org/api/v4/"
TOKEN="****************************************************************"
curl -X GET "${ENDPOINT}odpt:FlightInformationArrival?odpt:flightNumber=CX0520&acl:consumerKey=${TOKEN}"
データを調べてみる
マニュアルもありますが、具体的な内容を知るには実際のデータを見るのが一番。便で絞り込まずに全発着データをダウンロードして中身を確認しました。
#! /bin/sh
#~シェル変数省略~
curl -X GET "${ENDPOINT}odpt:FlightInformationArrival?acl:consumerKey=${TOKEN}"
curl -X GET "${ENDPOINT}odpt:FlightInformationDeparture?acl:consumerKey=${TOKEN}"
以下が現時点での成田と羽田発着便データの内容です。
@id(固有識別子)
必須パラメータなのに羽田便にはない。成田発着便のみ。
"@id":"*********************************************"
@type(クラス指定)
上が着便、下が発便(成田/羽田とも)。
"@type":"odpt:FlightInformationDeparture"
"@type":"odpt:FlightInformationArrival"
dc:data(データ生成日時)
"dc:date":"2017-12-19T11:35:02+09:00"
@context(JSON-LDに基づくurl情報)
これも必須なのに成田発着のみ。
"@context":"http://vocab.odpt.org/context_odpt.jsonld"
odpt:gate(ゲート番号)
上が成田発着、下が羽田発便。形式的に正しいのは羽田の方。不明の場合はnullが入ったり、そもそもパラメータがなかったりと状況はまちまち。
"odpt:gate":"164"
"odpt:gate":"odpt.AirportGate:HND.InternationalPassengerTerminal.113"
owl:sameAs(固有識別子)
上から成田発着、羽田発着。
"owl:sameAs":"odpt.FlightInformationDeparture:NRT.JJP.GK0503"
"owl:sameAs":"odpt.FlightInformationArrival:NRT.AMX.AM0058"
"owl:sameAs":"odpt.FlightInformationDeparture:HND.JL0033"
"owl:sameAs":"odpt.FlightInformationArrival:HND.MM0858"
odpt:airline(航空会社レターコード)
上が成田発着、下が羽田発着。
"odpt:airline":"odpt.Airline:JJP"
"odpt:airline":"JAL"
odpt:airport
仕様書にない。成田発着のみにある。
"odpt:airport":"odpt.Airport:NRT"
odpt:operator(データ提供事業者)
上が成田発着、下が羽田発着。
"odpt:operator":"odpt.Operator:NAA"
"odpt:operator":"odpt.Operator:HND-TIAT"
odpt:terminal(空港ターミナル)
上が成田発着で1から3まである。下は羽田発着。
"odpt:terminal":"odpt.AirportTerminal:NRT.Terminal3"
"odpt:terminal":"odpt.AirportTerminal:HND.InternationalPassengerTerminal"
odpt:viaAirport
仕様書にない。成田発着のみの経由地表示?
"odpt:viaAirport":"CTU"
odpt:flightStatus(フライト状況)
成田、羽田ともにある。パターンとしては”Takeoff”、”FinalCall”、”CheckIn”、”NowBoarding”、”Delayed”、”OnTime”、”NewTime”、”Tommorow”、”Arrived”、”BaggageAvailable”など。パラメータなしやnullもある。
"odpt:flightStatus":"odpt.FlightStatus:Takeoff"
odpt:flightNumber(便名)
仕様書上はflightNumber。成田発着はこちらに対応。1便1オブジェクトなので、共同運航便は便名のみ違うオブジェクトが存在する。
"odpt:flightNumber":"AM0058"
odpt:flightNumbers(便名)
何故か羽田は仕様書にないこちらのタイプ。共同運航便はひとつのオブジェクトにまとめられてしまう。
"odpt:flightNumbers":["JL0033","UL3357","PG4152"]
odpt:aircraftModel
仕様書にない。羽田のみ存在するもののnullしかない。
"odpt:aircraftModel":null
odpt:checkInCounters
仕様書にない。羽田のみ存在する。
"odpt:checkInCounters":["F","G"]
odpt:departureAirpor(出発地空港)
成田、羽田ともに仕様書通り。出発便は目的地、到着便は当地空港コード。
"odpt:departureAirport":"odpt.Airport:MEX"
odpt:destinationAirport(到着地空港)
成田、羽田ともに仕様書通り。到着便は目的地、出発便は当地空港コード。
"odpt:destinationAirport":"odpt.Airport:BKK"
odpt:scheduledTime(定刻離発着時刻)
成田、羽田とも仕様書通り。
"odpt:scheduledTime":"00:05"
odpt:estimatedTime(変更後の離発着時刻)
仕様書上は離発着後は取得できないとある。成田、羽田ともパラメータそのものがない場合と、nullが入っている場合の2パターンあり。
"odpt:estimatedTime":"07:09"
odpt:actualTime(実際の離発着時刻)
仕様書上は離発着するまでは存在しないとある。成田、羽田ともパラメータそのものがない場合と、nullが入っている場合の2パターンあり。
"odpt:actualTime":"00:00"
仕様書ではイメージしにくかったり、そもそも仕様書の内容がなかったり、逆に仕様書にない情報があったりするので、実際のデータを確認するのは大切です。
アプリケーションの概要
仕様というほど大したもんじゃないので、概要としました。
メール送受信スクリプト
- メインルーチンになります。FreeBSDでメール転送するで使った.forwardファイルにより起動されます。
- 受信メールからメールアドレスとタイトル(フライト番号が書いてある)を抜き出して、データ処理は他のスクリプトに投げます。
- 処理済みの結果を受信メールアドレス宛てに返信します。
データ取得スクリプト
- メインルーチンから受け取ったフライト番号を使って、オープンデータチャレンジAPIからJSONデータを取得します。
- タイムアウトなどでデータ取得に失敗してもいいように複数回トライします。
データ解析スクリプト
- データ取得スクリプトから受け取ったJSONデータを加工して、必要なデータを取り出します。
- 返信メールの文面に加工してメインルーチンに返します。
細かい内容は別稿にて。