公共交通オープンデータ API のお引越し

· Read in about 11 min · (5289 words) ·

大都市の地下に張り巡らされた9つの地下鉄路線を運営する東京メトロ。2014年にその地下鉄のデータを使ったアプリを開発するコンテスト「東京メトロ オープンデータコンテスト」が開かれました。私は友達を誘ってトイレ検索アプリ (本記事の最後で紹介します) を開発し、現在も運用・保守を続けています。

しかし、その当時から運営され続けてきたオープンデータ API とその開発者サイトが2022年3月末をもって廃止することになりました。 後継としては公共交通オープンデータ協議会 (odpt.org、以下 “協議会” と呼ぶことにします) が案内され、2022年2月24日からは協議会からの東京メトロのデータ提供が開始されています。

協議会でも開発コンテストが開催されていたため、そちらから公共系オープンデータに触れた方も少なくないかもしれません。

今回、前述のトイレ検索アプリの API を東京メトロから協議会へ切り替える作業を行なったので、API ユーザーとしての具体的な注意点・作業内容と、簡単な API 設計の考察をまとめたいと思います。

提供されるデータの種類

協議会のデータカタログ[参考文献1]によると、現在のところ鉄道、バス、飛行機、船などで37件の組織からデータが提供されているようです。 鉄道分野では以下の7事業者を見つけました (執筆時点)。

  • ゆりかもめ
  • 多摩都市モノレール
  • 東京メトロ
  • 東京臨海高速鉄道 (りんかい線)
  • 東京都交通局 (都営地下鉄、荒川線、都バス)
  • 横浜市交通局 (市営地下鉄、市バス)
  • 首都圏新都市鉄道 (つくばエクスプレス)

提供されているデータの種類を事業者ごとにまとめてみました (執筆時点)。

事業者 駅情報 駅時刻表 列車時刻表 運賃 運行 路線系統 乗降者数 列車ロケーション 画像等
ゆりかもめ ✔︎ ✔︎ - ✔︎ - ✔︎ - - ✔︎
多摩都市モノレール ✔︎ ✔︎ ✔︎ ✔︎ ✔︎ ✔︎ ✔︎ - ✔︎
東京メトロ ✔︎ ✔︎ ✔︎ ✔︎ ✔︎ ✔︎ ✔︎ (調整中) ✔︎
東京臨海高速鉄道 ✔︎ ✔︎ ✔︎ ✔︎ ✔︎ ✔︎ ✔︎ - ✔︎
東京都交通局 ✔︎ ✔︎ ✔︎ ✔︎ ✔︎ ✔︎ ✔︎ ✔︎ ✔︎
横浜市交通局 ✔︎ ✔︎ ✔︎ ✔︎ ✔︎ ✔︎ ✔︎ - -
首都圏新都市鉄道 ✔︎ ✔︎ ✔︎ ✔︎ ✔︎ ✔︎ ✔︎ - ✔︎

駅情報、駅時刻表、運賃といった基礎的なデータは網羅されていることがわかります。一方でリアルタイム性が高い列車ロケーション情報は提供体制がまだあまり整備されているとはいえません。 東京メトロ API ユーザー視点では、メトロ以外のデータも使えるようになったぞ!と思っても、期待したデータが提供されていなかったといった落とし穴があり得ます。

さて、ここまで来て東京メトロ API で使っていた ◯◯ がない!?という課題が浮かび上がりました。 東京メトロ API と協議会 API の提供データの違いもまとめてみました (執筆時点)。

データ 東京メトロ オープンデータ API 協議会 API の東京メトロのデータ
列車ロケーション情報 ✔︎ (調整中)
運行情報 ✔︎ ✔︎
駅時刻表 ✔︎ ✔︎
施設情報(駅施設情報) ✔︎ -
駅情報(乗降人員数) ✔︎ ✔︎
運賃情報 ✔︎ ✔︎
地物(駅出入口)情報 ✔︎ -
国土交通省国土数値情報 地物(駅)情報 ✔︎ -
国土交通省国土数値情報 地物(線路)情報 ✔︎ -
東京メトロ駅情報 ✔︎ ✔︎
東京メトロ路線情報 ✔︎ ✔︎

開発コンテストではロケーション情報を使ったアプリが目立っていたので、それらは3月末で一旦全滅することになります。残念ですね。

私が開発していたアプリはというと、以下の3つを利用していました。

  • 駅情報・・・協議会でも提供あり
  • 駅時刻表・・・協議会でも提供あり
  • 駅施設情報・・・協議会では未提供!

駅施設情報がない・・・!どうしよう!?対策はのちほど・・・・。

利用規約・ガイドラインの差異

そもそも協議会の API 提供周辺は東京メトロの活動を土台としてそのまま発展させているように見えます。API 仕様は基本的な設計方針を維持したまま発展した感じですし、API 仕様書から開発者サイトの作り方、フォーラムまでほとんど違いがありません。 利用規約やガイドラインについても共通点が多く、アナウンスされている大きな違いは商用目的での利用が可能になったことぐらいです。

なお東京メトロのほうの利用規約では、禁止事項として以下が挙げられていました。

公共交通データAPIを用いて得られた本公共交通データを、本webシステム以外のソフトウェア、データベース、アプリケーション、GPSシステムをはじめ、これらに限らない何等かのシステムに取り込み、または更新すること。

ただし以下のような内容は利用規約上禁止されていない旨、FAQ に記載されていました。

・アプリで駅名を検索する際、毎回データ検索APIを利用すると非効率なため、駅情報 odpt:Station をAPIからキャッシュ(DBに保存、ファイルに保存など)してアプリで活用すること

・データサイズの大きい時刻表などをキャッシュしてアプリで活用すること

・路線情報 odpt:Railway から抽出した路線の接続関係をグラフデータベースに取り込んで経路探索アプリなどを開発すること

・駅情報 odpt:Railway や路線情報 odpt:Station、駅出入口情報 ug:Poi から取得されるデータをGISデータベースに取り込んでアプリで活用すること

協議会のほうの利用規約では、取り込みに関する項目自体が禁止事項から削除されました。 代わりに開発者ガイドラインのほうに列車ロケーション情報・列車運行情報などのリアルタイム性の高い動的データに対し、データ生成時刻情報 dc:date を画面上に表示するなどの要求事項が盛り込まれました。 また静的データに対しても古い情報の提示による誤解や混乱を避けるため取得日時の表示や定期的な更新を求めています。逆に言えば、このガイドラインに従う限りはアプリケーション側で静的データはキャッシュして良いと解釈できます。

なお、ガイドラインでは公共交通オープンデータセンターから取得したデータを利用している旨掲示するなどの要求事項も記載されていますので、仮にごく簡単な修正で API 移行自体は完了できたとしても、必ず本ガイドラインを読んで要求事項に従って対応する必要があります。

これらをふまえた上で、私は協議会 API では提供されない東京メトロの駅施設情報はアプリケーション上にキャッシュして利用することにしました。 将来提供が再開されるまでは情報がアップデートされませんが、アプリを停止するよりはマシでしょう。ただし情報が古すぎて役に立たなくなってきたらアプリを停止する必要があるかもしれませんね・・・。

API 移行作業

さて、だいぶ前置きが長くなりましたが、ここから API 移行作業のメモです。 作業は以下の流れで行いました。

  1. 協議会 API ユーザー登録 (すぐに利用可能にならないので真っ先に着手!)
  2. アクセストークン発行
  3. API 仕様差異調査
  4. 廃止 API の対策検討
  5. API 仕様差異の実装

1. 協議会 API ユーザー登録

まずは以下の URL からユーザー登録を行います。

開発者サイト https://developer.odpt.org/

東京メトロのときもそうでしたが、登録しても承認されないとログインできるようになりません。 ユーザー登録画面には以下のように記載されています。

登録の申請をいただいた後、申請内容に問題がない場合、最大2営業日程度で承認完了のメールをお送りします。

私の場合は平日の朝に申し込んでたった45分で登録完了メールが届いてログインできるようになりました。 ログインすると、アクセストークンの発行や API 仕様書の閲覧が可能になります。

2. アクセストークン発行

ユーザー登録が完了したら、まずアクセストークンを発行します。

最初から DefaultApplication というトークンが発行されていますが、使い回しはせず用途別に発行してください。

3. API 仕様差異調査

原則的に HTTP と JSON-LD に基づいた RESTish な (RESTful ではない) APIで、大筋では大きく変わっていませんが、細かな差異はたくさんあります。

まずはエンドポイントから。おおまかに以下のような差異があります。

項目 東京メトロ 協議会
ホスト名 api.tokyometroapp.jp api.odpt.org
データ検索 API /api/v2/datapoints? /v4/RDF_TYPE?
データ取得 API /api/v2/datapoints/DATA_URI /v4/datapoints/$DATA_URI
データダンプ API - /v4/RDF_TYPE.json?
地物情報検索 API /api/v2/places? -
地物情報取得 API /api/v2/places/DATA_URI /v4/places/RDF_TYPE?

実際のデータ取得のリクエストは以下のようになります (銀座線の銀座駅の渋谷方面の駅時刻表を取得する例)。

東京メトロ:

curl -v "https://api.tokyometroapp.jp/api/v2/datapoints?rdf:type=odpt:StationTimetable&acl:consumerKey=<CONSUMER_KEY>&odpt:station=odpt.Station:TokyoMetro.Ginza.Ginza&odpt:railDirection=odpt.RailDirection:TokyoMetro.Shibuya"

協議会:

curl "https://api.odpt.org/api/v4/odpt:StationTimetable?acl:consumerKey=<CONSUMER_KEY>&odpt:station=odpt.Station:TokyoMetro.Ginza.Ginza&odpt:railDirection=odpt.RailDirection:TokyoMetro.Shibuya"

なお、協議会の API では事業者を指定するために odpt:operator=odpt.Operator:TokyoMetro を追加することもできます。上記の例では必要ありませんが、取得するデータの種類によっては指定したほうが良いでしょう。

個々の API に関しては、変更がさほどないものと、結構あるものがあります。 私のアプリでは、以下のような改修が必要になりました:

  • 駅情報
    • 駅施設情報の提供がなくなったため、駅施設情報への参照が消えた
  • 駅時刻表
    • 平日ダイヤ・土休日ダイヤなどの区分が odpt:Calendar を用いたモデルに全面的に書き換えられた
    • 行き先が文字列から文字列の配列になった (複数の行き先が刺せるモデルになった)
  • 駅施設情報
    • そもそも提供がなくなった

メトロや協議会が採用している JSON-LD はデータ間の参照を表現できるのが利点の一つですが、提供が終了すると当然その参照も消えるため、参照元にも変化が現れます。 今回は仕方ないので参照を自分で作ってむりやり協議会 API → キャッシュした東京メトロ API の駅施設データを繋げることにしました。なんて泥臭いコードなのでしょう。

/**
 * 駅施設の識別子を取得します。
 *
 * @return 駅施設の識別子
 */
public String getFacility() {
    if (facility == null) {
        // odpt.org はこの項目を提供していないため、 uniqueName から生成する
        return "odpt.StationFacility:TokyoMetro." + uniqueName.substring(uniqueName.lastIndexOf(".") + 1);
    }
    return facility;
}

odpt:Calendar は協議会 API でのみ利用可能な共通クラスで、odpt.Calendar:Weekday や事業者固有の休日などの日付の集合などを扱えるようになっています。curl "https://api.odpt.org/api/v4/odpt:Calendar?acl:consumerKey=<CONSUMER_KEY>" とすると全ての定義を取得できますが、大量にあって驚きます・・・。日付のモデリングって難しいですよね。

列車の複数の行き先が刺せるようになったのは、おそらく色々な公共交通に対応していく中で改修の必要性が迫られた例だと思いますが (逗子・葉山行+三崎口行とか・・・)、公共交通のモデル化の大変さが垣間見れますね。

4. 廃止 API の対策検討

廃止されてしまったデータを利用している場合、どう対応するか悩ましいです。 いくつか選択肢が考えられます。

  1. アプリの提供を終了する
  2. 当該データを必要とする機能をドロップし、提供再開を祈りながら待つ
  3. 当該データの現時点のスナップショットをキャッシュ、提供再開を祈りながら待つ
  4. 別の API を探す or ユーザー生成コンテンツ化など

たくさんの種類のオープンデータに手を出した人ほど今回の影響を受けてしまうので、今までの意欲的なデータ提供に感謝しつつ、もう少し救済措置が欲しかったかなとは思います。

5. API 仕様差異の実装

私の作ったアプリでは、API の応答データを何パターンかテストデータとして保存しておき、それをアプリケーションに食わせるユニットテストをたくさん用意していました。 今回の API 移行に関しては、この仕組みがとても役に立ちました。新仕様の応答データを食わせて失敗するテストを潰していくことで、効率よく API 仕様変更に対応することができました。 もっとも、交通事情も日々変化しており (虎ノ門ヒルズ駅が出来ただの、S-TRAIN が運行開始しただの)、一度テストデータ用意すれば将来も安泰とはならない難しさもありますが、オープンデータは基本データを HTTP GET するだけでサーバー側の状態などに依存するものがなく、構造的にユニットテストがやりやすい分野だと思います。

John Metro

それでは改修を終えたオープンデータを使うアプリをご覧ください。

電車に乗っているとき、急にお腹が痛くなったことはありませんか? このアプリは、駅名を入れて検索すると、何号車で降りればトイレに最速でたどり着けるかを瞬時に示すことができるアプリです。

John Metro

https://johnmetro.herokuapp.com/

John Metro

おまけ機能として、トイレの評価機能、落書き機能なども用意してあります。もしトイレの壁に落書きしたくなったら、ぐっとこらえて John Metro に書き込んでください。

駅の検索には駅情報 odpt:Station を、トイレの位置や属性情報は駅施設情報 odpt:StationFacility、トイレを済ませたあと次の電車の来る時刻を確認できる発車案内欄には駅時刻表 odpt:StationTimetable を利用しています。祝日の判定には現在内閣府の配布している syukujitsu.csv[参考文献2] を利用していますが、今回の移行で odpt:Calendar への移行も考え始めました。

技術的には、実装は Java と Spring Boot、DB に MongoDB Atlas、ホスティングに Heroku を利用しています。初期はもっと別のものを使っていたのですが、何回かの改修を経て現在の形に落ち着きました。MongoDB の mLab から Atlas への移行はこちらの記事に紹介があります。実はここで移行作業していた MongoDB のデータベースは John Metro のトイレ評価を溜め込んだ DB なのでした。

API 移行にともない、今後は駅施設情報は2022年3月末の状態からアップデートされなくなります。東京メトロには、ぜひ施設情報の再提供をお願いしたいところです。 東京メトロの事務局には駅設備データの提供再開を要望していますが、執筆時点までに回答はありません。

Happy hacking!

参考文献

  1. データセット - 公共交通オープンデータセンター データカタログサイト
  2. 国民の祝日について - 内閣府