ここがつらいよ東京公共交通オープンデータチャレンジAPI

12/7から公共交通オープンデータ協議会主催で東京公共交通オープンデータチャレンジが開催されています。

これは東京メトロ発足10周年を記念して開催された東京メトロオープンデータ活用コンテストと同様に、各種公共交通機関の静的データ(一部動的データ)を広く公開しているものです。

既にQiitaでもいくつかこれに関するエントリーが挙がっていますが、ここではAndroidアプリ向けにAPIを触ってみた感想の中でも、事業者ごとの差異でつらかった点を書いてみます。

※ただし、触ったのは鉄道系APIとバス系APIで、航空系APIはまだ触っていません

2017/12/21修正:復帰したようです。
なお、本日(12/20)の日付が変わる前あたりから開発者サイトとAPIが落ちていて使えない状況です。

全般

いつになったらデータ提供してくれるの?

コンテストが始まって2週間ですが、まだデータを公開していない事業者が結構あります。

バス系APIのドキュメントの質が…

鉄道系API以外のドキュメントが粗削りです。他のAPIからコピペしたのか、結構誤っているものも多いです。

鉄道系API

運賃情報API

特に目立った綻びはないように感じました。

鉄道路線情報API

運行系統名(dc:title)のフォーマットが事業者によって違う

例えば路線名が「○○線」の場合、「○○線」で送られてくる事業者と「○○」で送られてくる事業者とがあります。前者は東京メトロと東京臨海高速鉄道で、それ以外は後者です。

末尾に「線」がなければ補ってやればよいかというと、「東武スカイツリーライン」や「東武アーバンパークライン」が存在するので罠があります。

都営のデータが怪しい

API仕様にはない「odpt:travelTime」という項目が存在します。

この項目は(今のところ)どのAPIで送られてくるか明示されていない状態で定義自体はありますが、その定義とも一部内容に矛盾があります。具体的には、「odpt:necessaryTime」が「分」で定義されているのに、明らかに「秒」が入っています。

下記の例は三田線目黒駅から白金台駅までのデータですが、流石に120分も掛からないと思います。

三田線目黒駅と白金台駅
{"odpt:toStation":"odpt.Station:Toei.Mita.Shirokanedai",
"odpt:trainType":"odpt.TrainType:Local",
"odpt:fromStation":"odpt.Station:Toei.Mita.Meguro",
"odpt:necessaryTime":120}

京成電鉄の駅ナンバリングが独特

これはデータの不備というわけではありませんが、路線毎ではなく全線で連番を振っているため、番号が揃っていないので注意が必要です。

参考:京成電鉄路線図(PDF)

下記の例は金町線のデータの抜粋です。

京成金町線
{"odpt:stationOrder":[
{"odpt:index":10,
"odpt:station":"odpt.Station:Keisei.Kanamachi.KeiseiTakasago",
"odpt:stationTitle":"京成高砂"},
{"odpt:index":50,
"odpt:station":"odpt.Station:Keisei.Kanamachi.Shibamata",
"odpt:stationTitle":"柴又"},
{"odpt:index":51,
"odpt:station":"odpt.Station:Keisei.Kanamachi.KeiseiKanamachi",
"odpt:stationTitle":"京成金町"}]}

京成高砂駅は京成本線で先に番号が振られているため、連番になっていません。

データにtypoがある

2017/12/21追記

現時点で路線情報APIに限り、東京臨海高速鉄道りんかい線の路線ID(owl:sameAs)が「odpt.Railway:odpt.Station:TWR.Rinkai」になっています。正しくは「odpt.Railway:TWR.Rinkai」のはずです。sameAsは他のAPIにアクセスするときの検索条件として利用するので注意が必要です。(駅情報APIは正しい路線IDで検索できました)

運賃情報API

固有識別子別名(owl:sameAs)のフォーマット違反がある

仕様での命名ルールは「odpt.RailwayFare:出発駅の会社名.出発駅の路線名.出発駅名.到着駅の会社名.到着駅の路線名.到着駅名」ですが、
東京メトロ以外の事業者では「odpt.RailwayFare:出発駅の会社名.出発駅の路線名.出発駅名.到着駅の路線名.到着駅名」と、「到着駅の会社名」がありません。

下記の例は都営三田線三田駅から都営浅草線馬込駅のデータです。

都営三田線三田駅発_都営浅草線馬込駅着
[{"@id":"urn:ucode:_00001C000000000000010000030E6CB2",
"@type":"odpt:RailwayFare",
"dc:date":"2016-06-08T16:33:18+09:00",
"@context":"http://vocab.odpt.org/context_odpt.jsonld",
"owl:sameAs":"odpt.RailwayFare:Toei.Mita.Mita.Asakusa.Magome",
"odpt:operator":"odpt.Operator:Toei",
"odpt:toStation":"odpt.Station:Toei.Asakusa.Magome",
"odpt:icCardFare":216,
"odpt:ticketFare":220,
"odpt:fromStation":"odpt.Station:Toei.Mita.Mita",
"odpt:childIcCardFare":108,
"odpt:childTicketFare":110}]

仕様に則っていれば「odpt.RailwayFare:Toei.Mita.Mita.Toei.Asakusa.Magome」のはずです。

データにtypoがある

東武鉄道のサイトに則れば東上線大山駅が「odpt.Station:Tobu.Tojo.Oyama」のはずが、「odpt.Station:Tobu.Tojo.Uyama」になっている気がします。

参考:大山駅 | 路線図・駅情報 | 東武鉄道

大山駅?
[{"@id":"urn:ucode:_00001C000000000000010000030EFFB4",
"@type":"odpt:RailwayFare",
"dc:date":"2016-12-12T17:53:50+09:00",
"@context":"http://vocab.odpt.org/context_odpt.jsonld",
"owl:sameAs":"odpt.RailwayFare:Tobu.Tojo.Uyama.Tojo.Wakoshi",
"odpt:operator":"odpt.Operator:Tobu",
"odpt:toStation":"odpt.Station:Tobu.Tojo.Wakoshi",
"odpt:icCardFare":195,
"odpt:ticketFare":200,
"odpt:fromStation":"odpt.Station:Tobu.Tojo.Uyama",
"odpt:childIcCardFare":97,
"odpt:childTicketFare":100}]

駅情報API

特に目立った綻びはないように感じました。

駅時刻表API

特に目立った綻びはないように感じました。

列車情報(列車ロケーション)API

現在取得可能なJR東日本と東京メトロの両方で、仕様にない項目が多く乗っている気がします。(odpt:○○Titleを除く)

まだ都営の情報が取れないので何とも言えませんが、事業者ごとに作り分けた方がいいかもしれません。(常磐緩行線と千代田線、三田線と南北線などが厄介そうですが)

JR東日本の例
{"@id":"urn:uuid:e0e9e14f-2b64-4be4-913c-8dc8821e1442",
"@type":"odpt:Train",
"dc:date":"2017-12-15T15:47:34+09:00",
"@context":"http://vocab.odpt.org/context_odpt.jsonld",
"odpt:delay":0,
"odpt:index":2,
"owl:sameAs":"odpt.Train:JR-East.Takasaki.843M",
"odpt:railway":"odpt.Railway:JR-East.Takasaki",
"odpt:operator":"odpt.Operator:JR-East",
"odpt:toStation":"odpt.Station:JR-East.Takasaki.Urawa",
"odpt:fromStation":"odpt.Station:JR-East.Takasaki.Akabane",
"odpt:trainNumber":"843M",
"odpt:railDirection":"odpt.RailwayDirection:Outbound",
"odpt:carComposition":15,
"odpt:toStationTitle":"浦和",
"odpt:trainTypeTitle":"普通",
"odpt:fromStationTitle":"赤羽",
"odpt:destinationStation":"odpt.Station:JR-East.Takasaki.Kagohara"}
東京メトロの例
{"@id":"urn:ucode:_00001C00000000000001000003101DF3",
"@type":"odpt:Train",
"dc:date":"2017-12-15T15:50:42+09:00",
"@context":"http://vocab.odpt.org/context_odpt.jsonld",
"dct:valid":"2017-12-15T15:51:12+09:00",
"odpt:delay":0,
"owl:sameAs":"odpt.Train:TokyoMetro.Ginza.A1551",
"odpt:railway":"odpt.Railway:TokyoMetro.Ginza",
"odpt:operator":"odpt.Operator:TokyoMetro",
"odpt:frequency":30,
"odpt:toStation":null,
"odpt:trainType":"odpt.TrainType:TokyoMetro.Local",
"odpt:trainOwner":"odpt.TrainOwner:TokyoMetro",
"odpt:fromStation":"odpt.Station:TokyoMetro.Ginza.Asakusa",
"odpt:trainNumber":"A1551",
"odpt:railDirection":"odpt.RailDirection:TokyoMetro.Shibuya",
"odpt:startingStation":"odpt.Station:TokyoMetro.Ginza.Asakusa",
"odpt:terminalStation":"odpt.Station:TokyoMetro.Ginza.Shibuya"}

列車運行情報API

各社によって全く挙動が異なる

これが本当に困りもので、昨日までに取得できたJR東日本・都営・東京メトロで全く挙動が変わります。

事業者 平常運行の路線のデータ 運行支障のある路線のデータ
JR東日本 取れない 当日分の履歴含め古い順から全件
都営 最新1件のみ 取れない
東京メトロ 最新1件のみ 最新1件のみ

東京メトロのオープンデータAPIと同じだと思っていると痛い目を見ます。

JR東日本の場合

路線毎に、当日支障が生じていれば履歴情報含め1件以上のデータが返されます。つまり路線毎に以下のように判断します。

  • 1件もデータがない場合、当日は全く運行に支障がない。つまり現時点でも運行に支障は生じていない
  • 1件以上データがある場合、発生時刻(odpt:timeOfOrigin)が最も新しいデータを見て、現時点で運行に支障が生じているか判断するしかない

また、JR東日本の場合は発生場所等駅IDを引く項目がなく、代わりに駅名で返ってくることにも注意が必要です。

更に列車運行情報APIに限り、進行方面ID(odpt:railDirectionのフォーマットが仕様で定められた「odpt:RailDirection:方面名」ではなく「odpt:railDirection:方面名」になっていることに注意が必要です。

東京メトロの場合

路線毎に、現時点で運行に支障があろうとなかろうと必ず1件のデータが取得できるため、路線毎に以下のように判断します。

  • データに運行情報(odpt:trainInformationStatus)が存在しない場合、現時点で運行に支障は生じていない
  • データに運行情報が存在する場合、現時点で運行に支障が生じている

都営の場合

路線毎に、現時点で運行に支障がなければ運行情報(odpt:trainInformationStatus)が存在しないデータが最新1件返ってきますが、運行に支障がある場合はデータそのものが送信されません。従って路線毎に以下のように判断します。

  • データが存在する場合、現時点で運行に支障は生じていない
  • データが存在しない場合、現時点で運行に支障が生じている。ただし詳細情報は分からない

また都営の場合、API仕様上でrequiredである発生時刻(odpt:timeOfOrigin)が存在しないことにも注意が必要です。(まあ、そもそも運行に支障が生じているとデータそのものが返ってこないので意味がないですが)

更に列車運行情報APIに限り、都電荒川線の路線IDが「odpt.Railway:Toei.TodenArakawa」ではなく「odpt.Railway:Toei.TodeArakawa」とtypoされているという、酷い状況が発生しています。

列車時刻表API

JR東日本の場合に終着駅かの判断に悩む

現時点で取得できるJR東日本・都営・東京メトロで、それぞれ微妙にフォーマットが違います。ただし、仕様から大きく逸脱しているわけではないのでそれほど気になるものではありません。

それよりも気になるのが、列車時刻表データ(odpt:trainTimetableObject)において、JR東日本の場合に終着駅かどうか判断できないデータがある事です。

JR東日本常磐緩行線1247E列車(平日)の抜粋
[{"@id":"urn:ucode:_00001C00000000000001000003107EA8",
"@type":"odpt:TrainTimetable",
"dc:date":"2017-12-07T23:43:47+09:00",
"@context":"http://vocab.odpt.org/context_odpt.jsonld",
"owl:sameAs":"odpt.TrainTimetable:JR-East.JobanLocal.1247E.Weekday",
"odpt:railway":"odpt.Railway:JR-East.JobanLocal",
"odpt:calendar":"odpt.Calendar:Weekday",
"odpt:operator":"odpt.Operator:JR-East",
"odpt:trainType":"odpt.TrainType:JR-East:Local",
"odpt:trainNumber":"1247E",
"odpt:railDirection":"odpt.RailDirection:Outbound",
"odpt:trainTimetableObject":[
    {"odpt:index":1,
    "odpt:departureTime":"14:01",
    "odpt:departureStation":"odpt.Station:JR-East.JobanLocal.Ayase"},
    {"odpt:index":2,
    "odpt:departureTime":"14:03",
    "odpt:departureStation":"odpt.Station:JR-East.JobanLocal.Kameari"},

    {"odpt:index":11,
    "odpt:departureTime":"14:27",
    "odpt:departureStation":"odpt.Station:JR-East.JobanLocal.KitaKashiwa"},
    {"odpt:index":12,
    "odpt:departureTime":"14:30",
    "odpt:departureStation":"odpt.Station:JR-East.JobanLocal.Abiko"}
]}]

終着駅のデータに存在すべき到着時間(odpt:arrivalTime)や到着駅駅ID(odpt:arrivalStation)がなく、逆に終着駅のデータに存在しないはずの出発時間(odpt:departureTime)や出発駅駅ID(odpt:departureStation)があります。

仕様ではこれらの有無で始発駅・終着駅・途中停車駅の区別を判断せよとあるので困ったことになります。この列車は我孫子から成田線に乗り入れするのかな?と思いましたが、常磐線1247E列車の行き先は我孫子なので、そういう事でもないようです。

また手元にデータがないのですが、JR東日本でも到着時間や到着駅駅IDのあるデータもあったため、JR東日本の場合は仕様にない「odpt:index」を使って、もっとも大きければ終着駅と判断するのがよいのかもしれません。

バス系API

全般

小田急バスの日付時刻フォーマットが異なる

基本的に鉄道系APIも含め、日付時刻フォーマットを要求されている項目はISO_OFFSET_DATE_TIMEフォーマット(例:"2017-12-13T15:52:57+09:00")で返ってきますが、現時点で小田急バスのデータ保証期限(dct:valid)のみISO_DATEフォーマット(例:"2018-01-15")で返ってきます。日付時刻型にパースする時に痛い目を見ました。

バス情報(バスロケーション情報)API

特に目立った綻びはないように感じました。

バス運行路線情報

odpt:busstopPoleOrderの停留所通過順(odpt:index)が0から始まる事業者と1から始まる事業者が存在しますが、リクエストに与える情報ではないのであまり気にすることはないでしょう。

バス運賃情報API

:poop::poop::poop::poop::poop::poop::poop::poop:

使うべきではないと思います。どうせ均一区間の多い都営しか使えませんし。

バス停標柱情報API

特に目立った綻びはないように感じました。

バス停標柱時刻表API

特に目立った綻びはないように感じました。取れたのが都営だけだからかもしれません。

バス時刻表API

バス時刻表時分情報(odpt:busstopPoleOrder)の標柱通過順(odpt:index)が0から始まる事業者と1から始まる事業者が存在しますが、リクエストに与える情報ではないのであまり気にすることはないでしょう。