Posted at

Go言語で東京メトロAPIを叩く

More than 3 years have passed since last update.

東京メトロがWebAPIで色々な情報を提供しているようなので早速使ってみました。

東京メトロ オープンデータ 開発者サイト

元々はコンテスト用に公開してたAPIがそのまま使えるようになったみたいですね。


ユーザ登録

APIの利用にはユーザ登録が必要です。登録は無料です。

申請内容の確認から登録まで最大で2営業日ほどお時間を、とありましたが自分が登録した時は数分で完了しました。


アクセストークンの取得

登録が完了したら1個デフォルトのアクセストークンが発行されていると思いますので、今回はそれを使ってアクセスしてみましょう。

ログインして「アクセストークンの確認・追加」から確認できます。


いざデータ取得

今回は運行情報を取得してみます。

→ API仕様: 列車運行情報 odpt:TrainInformation


main.go

package main

import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"strings"
"time"
)

const (
ENDPOINT = "https://api.tokyometroapp.jp/api/v2/datapoints"
CONSUMER_KEY = <your consumer key>
)

// レスポンスJSONデータ用構造体
type TrainInfomation struct {
Context string `json:"@context"`
Id string `json:"@id"`
Type string `json:"@type"`
Date time.Time `json:"dc:date"`
Valid time.Time `json:"dct:valid"`
Operator string `json:"odpt:operator"`
TimeOfOrigin time.Time `json:"odpt:timeOfOrigin"`
Railway string `json:"odpt:railway"`
TrainInformationStatus string `json:"odpt:trainInformationStatus"`
TrainInformationText string `json:"odpt:trainInformationText"`
}

// レスポンスJSONデータ配列
type TrainInformations []TrainInfomation

func main() {
// URL生成
q := map[string]string{
"rdf:type": "odpt:TrainInformation", // TypeにTrainInformation(運行情報)を設定
"acl:consumerKey": CONSUMER_KEY, // アクセストークン
}
url := fmt.Sprintf("%s?%s", ENDPOINT, buildQuery(q))
// URLを叩いてデータを取得
resp, err := http.Get(url)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
// 取得したデータをJSONデコード
var trains TrainInformations
err = json.Unmarshal(body, &trains)
if err != nil {
log.Fatal(err)
}
// 取得したデータを整形して出力する
for _, train := range trains {
// 路線名
railway := strings.Replace(train.Railway, "odpt.Railway:TokyoMetro.", "", -1)
// 運行情報を組み立てる
text := train.TrainInformationText
if len(train.TrainInformationStatus) > 0 {
text = fmt.Sprintf("%s (%s)", train.TrainInformationStatus, train.TrainInformationText)
}
fmt.Printf("%s: %s [%s]\n", railway, text, train.Date)
}
}
func buildQuery(q map[string]string) string {
queries := make([]string, 0)
for k, v := range q {
qq := fmt.Sprintf("%s=%s", k, v)
queries = append(queries, qq)
}
return strings.Join(queries, "&")
}


Fukutoshin: 現在、平常どおり運転しています。 [2016-05-16 23:10:03 +0900 JST]

Hanzomon: 現在、平常どおり運転しています。 [2016-05-16 23:10:03 +0900 JST]
Hibiya: 現在、平常どおり運転しています。 [2016-05-16 23:10:03 +0900 JST]
Ginza: 現在、平常どおり運転しています。 [2016-05-16 23:10:03 +0900 JST]
Chiyoda: ダイヤ乱れ (21時23分頃、JR常磐線各駅停車内で地震のため、ダイヤが乱れ ています。只今、東京メトロ線、都営地下鉄線、JR線、東急線、東武線、京成線、小田急線、京王線、つくばエクスプレス線に振替輸送を実施しています。詳しくは、駅係員にお尋ねください。) [2016-05-16 23:10:03 +0900 JST]
Namboku: 現在、平常どおり運転しています。 [2016-05-16 23:10:03 +0900 JST]
Marunouchi: 現在、平常どおり運転しています。 [2016-05-16 23:10:03 +0900 JST]
Yurakucho: 現在、平常どおり運転しています。 [2016-05-16 23:10:03 +0900 JST]
Tozai: 現在、平常どおり運転しています。 [2016-05-16 23:10:03 +0900 JST]

こういうのをサクッと作れるのもGo言語の強みですね。

時間があったらAPIのラッパーライブラリを作ろうと思います。