Google Map Directions API で日本国内の路線検索はできない

# 概要
最近、帰宅報告なんかを色々なサービス使って作ってる記事が多いじゃないですか。
そういうのの一環で、帰宅報告のついでに帰宅予想時間とか書けると面白そうじゃないかと考えてみたわけですよ。

```
今から帰ります！
20時25分ぐらいに着くので、よろしくね！
```
みたいなのですよ。

それで *Google Map Directions API* 使ってみたんですけど、思ったのじゃなかったですの記事です。

# Google Map Directions API
簡単に説明すると、Google Mapの経路検索をAPI化したサービスです。
https://developers.google.com/maps/documentation/directions/?hl=ja

到着時間とかルートを取得できます。
経由地や避けたい場所を指定することも可能なようです。

説明では、使用できる経路が、
- `driving` (車)
- `transit`（電車）
- `walking`（徒歩）
- `bicycling` (自転車)
となってたので、こいつは使えるはずだ、と意気揚々でしたね。

基本的な使用は無料ですが、使用制限が以下に載ってます。
https://developers.google.com/maps/documentation/directions/usage-limits?hl=ja
1日2500回のリクエストまで無料なので、テスト程度では余裕で使えると思います。

## APIキーの取得
使うにはAPIキーが必要です。
上記説明ページ内の`キーの取得`をクリックしますが、プロジェクト選べ、となります。

![project_select.png](https://qiita-image-store.s3.amazonaws.com/0/7690/997deb9e-479c-3f8c-5591-df4a0f5238d6.png)

Googleの環境にプロジェクトがないと使わせてくれないようです。
`+ Create a new project` を選択して適当にプロジェクト名を入力します。
`NEXT`を押すと作成処理が開始、APIキーが生成されます。

![スクリーンショット 2018-04-18 0.56.16.png](https://qiita-image-store.s3.amazonaws.com/0/7690/a6d79abd-048b-2506-b15f-2c824dc82e60.png)

`YOUR API KEY` をメモってやってください。

## 使い方
ここに書いてある通りです。
https://developers.google.com/maps/documentation/directions/start?hl=ja

```
https://maps.googleapis.com/maps/api/directions/json?origin=Disneyland&destination=Universal+Studios+Hollywood4&key=YOUR_API_KEY
```

とりあえずサンプル通り上記URLの `YOUR_API_KEY` を変更すると使えます。

代表的なパラメータは以下でしょうか。

|パラメータ名|内容|セットする値|
|:---|:---|:---|
|origin|開始地点|エスケープした住所の文字列か、緯度経度の数字をカンマで繋ぐか|
|destination|到着地点|同上|
|mode|移動方法|driving、transit、walking、bicycling|
|units|使用する単位|metric(メートル)、imperial(ヤード)|
|region|優先する地域コード|us、jaなど|
|departure_time|出発時刻|指定しない場合は現在時刻|
|arrival_time|到着予定時刻|指定しないとなし|

jsonで結果が返ってきます。こんなの。

```json
{
   "geocoded_waypoints" : [
      {
         "geocoder_status" : "OK",
         "place_id" : "ChIJRVY_etDX3IARGYLVpoq7f68",
         "types" : [
            "bus_station",
            "transit_station",
            "point_of_interest",
            "establishment"
         ]
      },
      {
         "geocoder_status" : "OK",
         "partial_match" : true,
         "place_id" : "ChIJp2Mn4E2-woARQS2FILlxUzk",
         "types" : [ "route" ]
      }
   ],
   "routes" : [
      {
         "bounds" : {
            "northeast" : {
               "lat" : 34.1330949,
               "lng" : -117.9143879
            },
            "southwest" : {
               "lat" : 33.8068768,
               "lng" : -118.3527671
            }
         },
         "copyrights" : "Map data ©2016 Google",
         "legs" : [
            {
               "distance" : {
                  "text" : "35.9 mi",
                  "value" : 57824
               },
               "duration" : {
                  "text" : "51 mins",
                  "value" : 3062
               },
               "end_address" : "Universal Studios Blvd, Los Angeles, CA 90068, USA",
               "end_location" : {
                  "lat" : 34.1330949,
                  "lng" : -118.3524442
               },
               "start_address" : "Disneyland (Harbor Blvd.), S Harbor Blvd, Anaheim, CA 92802, USA",
               "start_location" : {
                  "lat" : 33.8098177,
                  "lng" : -117.9154353
               },

  ... Additional results truncated in this example[] ...


         "overview_polyline" : {
            "points" : "knjmEnjunUbKCfEA?_@]@kMBeE@qIIoF@wH@eFFk@WOUI_@?u@j@k@`@EXLTZHh@Y`AgApAaCrCUd@cDpDuAtAoApA{YlZiBdBaIhGkFrDeCtBuFxFmIdJmOjPaChDeBlDiAdD}ApGcDxU}@hEmAxD}[tt@yNb\\yBdEqFnJqB~DeFxMgK~VsMr[uKzVoCxEsEtG}BzCkHhKWh@]t@{AxEcClLkCjLi@`CwBfHaEzJuBdEyEhIaBnCiF|K_Oz\\
            {MdZwAbDaKbUiB|CgCnDkDbEiE|FqBlDsLdXqQra@kX|m@aF|KcHtLm@pAaE~JcTxh@w\\`v@gQv`@}F`MqK`PeGzIyGfJiG~GeLhLgIpIcE~FsDrHcFfLqDzH{CxEwAbBgC|B}F|DiQzKsbBdeA{k@~\\oc@bWoKjGaEzCoEzEwDxFsUh^wJfOySx[uBnCgCbCoFlDmDvAiCr@eRzDuNxC_EvAiFpCaC|AqGpEwHzFoQnQoTrTqBlCyDnGmCfEmDpDyGzGsIzHuZzYwBpBsC`CqBlAsBbAqCxAoBrAqDdDcNfMgHbHiPtReBtCkD|GqAhBwBzBsG~FoAhAaCbDeBvD_BlEyM``@uBvKiA~DmAlCkA|B}@lBcChHoJnXcB`GoAnIS~CIjFDd]A|QMlD{@jH[vAk@`CoGxRgPzf@aBbHoB~HeMx^eDtJ}BnG{DhJU`@mBzCoCjDaAx@mAnAgCnBmAp@uAj@{Cr@wBPkB@kBSsEW{GV}BEeCWyAWwHs@qH?
            cIHkDXuDn@mCt@mE`BsH|CyAp@}AdAaAtAy@lBg@pCa@jE]fEcBhRq@pJKlCk@hLFrB@lD_@xCeA`DoBxDaHvM_FzImDzFeCpDeC|CkExDiJrHcBtAkDpDwObVuCpFeCdHoIl\\uBjIuClJsEvMyDbMqAhEoDlJ{C|J}FlZuBfLyDlXwB~QkArG_AnDiAxC{G|OgEdLaE`LkBbEwG~KgHnLoEjGgDxCaC`BuJdFkFtCgCnBuClD_HdMqEzHcBpB_C|BuEzCmPlIuE|B_EtDeBhCgAdCw@rCi@|DSfECrCAdCS~Di@jDYhA_AlC{AxCcL`U{GvM_DjFkBzBsB`BqDhBaEfAsTvEmEr@iCr@qDrAiFnCcEzCaE~D_@JmFdGQDwBvCeErEoD|BcFjC}DbEuD~D`@Zr@h@?d@Wr@}@vAgCbEaHfMqA`Cy@dAg@bAO`@gCi@w@W"
         },
         "summary" : "I-5 N and US-101 N",
         "warnings" : [],
         "waypoint_order" : []
      }
   ],
   "status" : "OK"
}
```

とりあえず、`routes` - `legs` の `distance` と `duration` が距離と時間になるようです。

この辺りをごにょごにょすれば使えるんやで、ということを覚えとけばいいでしょう。

## 検索してみた
例によってPythonでサンプル作ってみたわけですよ。

```python
import urllib
import json
import os

# 位置座標クラス
class MapCoordinate:
    def __init__(self, latitude, longitude):
        self.latitude = latitude
        self.longitude = longitude

    def position(self):
        return "{0},{1}".format(self.latitude, self.longitude)

# ルートクラス
class MapRoute:
    mode_driving = "driving"
    mode_walking = "walking"
    mode_bicycling = "bicycling"
    mode_transit = "transit"

    def __init__(self, src, dest, mode):
        self.src = src
        self.dest = dest
        self.mode = mode
        self.lang = "ja"
        self.units = "metric"
        self.region = "ja"

# Goolge Map Direction 取得
def getGoogleMapDirection(route):

    # Goolge Map Direction API トークン
    api_key = os.environ["GOOGLE_MAP_API_KEY"]

    # Google Maps Direction API URL
    url = "https://maps.googleapis.com/maps/api/directions/json?origin={0}&destination={1}&mode={2}&language={3}&units={4}&region={5}&key={6}"

    try:
        # GET通信
        api_url = url.format(
            route.src.position(),
            route.dest.position(),
            route.mode,
            route.lang,
            route.units,
            route.region,
            api_key)
        html = urllib.urlopen(api_url)

        html_json = json.loads(html.read().decode('utf-8'))
        return html_json

    except Exception as e:
        raise e
```

これで、

```python
src = MapCoordinate(34.733165, 135.500214) # 新大阪駅
dest = MapCoordinate(34.686669, 135.519586) # 大阪府庁舎
route = MapRoute(src, dest, MapRoute.mode_transit)

direction_json = getGoogleMapDirection(route)
```

みたいにして、取得したところ、、、

```json
{
   "available_travel_modes" : [ "DRIVING", "WALKING" ],
   "geocoded_waypoints" : [ {}, {} ],
   "routes" : [],
   "status" : "ZERO_RESULTS"
}
```

？？なんやこの結果？？ と思って調べてみたら。

https://stackoverflow.com/questions/36640874/how-to-set-travel-mode-to-transit-in-google-map-direction-api
> The Google Maps Directions Service supports all of the transit providers listed in the Transit Coverage List, except for those in Japan.

!?

https://developers.google.com/maps/faq#transit_directions_countries
> Google マップのルートサービスでは、交通機関の対象リストに記載されているすべての交通機関（日本を除く）をサポートしています。

なんてこった日本。
何かしらのパワーを感じるぜ、、、

ということで、日本で使用できるのは `walking` と `driving` の2モードのみのようです。

上記の処理を `MapRoute.mode_driving`にすると無事結果が返ってきました！

```json
{
   "geocoded_waypoints" : [
      {
         "geocoder_status" : "OK",
         "place_id" : "ChIJJab3ZDnkAGARuP4x7mqZCAM",
         "types" : [ "route" ]
      },
      {
         "geocoder_status" : "OK",
         "place_id" : "ChIJdbNzgi7nAGARndYTVDBnPIo",
         "types" : [ "route" ]
      }
   ],
   "routes" : [
      {
         "bounds" : {
            "northeast" : {
               "lat" : 34.7331109,
               "lng" : 135.5208023
            },
            "southwest" : {
               "lat" : 34.6856258,
               "lng" : 135.4987354
            }
         },
         "copyrights" : "地図データ ©2018 Google, ZENRIN",
         "legs" : [
            {
               "distance" : {
                  "text" : "7.2 km",
                  "value" : 7190
               },
               "duration" : {
                  "text" : "18分",
                  "value" : 1069
               },
               "end_address" : "日本、大阪府大阪市中央区 上町筋",
               "end_location" : {
                  "lat" : 34.6868503,
                  "lng" : 135.520398
               },
               "start_address" : "Unnamed Road, ５丁目-１６ 西中島 淀川区 大阪市 大阪府 532-0011 日本",
               "start_location" : {
                  "lat" : 34.7330081,
                  "lng" : 135.5002897
               },
               "steps" : [
                  {
                     "distance" : {
                        "text" : "0.3 km",
                        "value" : 261
                     },
                     "duration" : {
                        "text" : "1分",
                        "value" : 67
                     },
                     "end_location" : {
                        "lat" : 34.7314536,
                        "lng" : 135.5001444
                     },
                     "html_instructions" : "\u003cb\u003e東\u003c/b\u003eに進む",
                     "polyline" : {
                        "points" : "ix~rEy{_zXQy@AI@MDYJQJE\\KL?PARD\\H^RXP`@h@n@d@n@h@"
                     },
                     "start_location" : {
                        "lat" : 34.7330081,
                        "lng" : 135.5002897
                     },
                     "travel_mode" : "DRIVING"
                  },
                  {
                     "distance" : {
                        "text" : "0.3 km",
                        "value" : 335
                     },
                     "duration" : {
                        "text" : "1分",
                        "value" : 34
                     },
                     "end_location" : {
                        "lat" : 34.7287408,
                        "lng" : 135.4987354
                     },
                     "html_instructions" : "\u003cb\u003e右側\u003c/b\u003eのランプから \u003cb\u003e難波・淀屋橋\u003c/b\u003e 方面に進む",
                     "polyline" : {
                        "points" : "qn~rE{z_zXtE~CbBbALJVHXD^BbA?L@PF^H"
                     },
                     "start_location" : {
                        "lat" : 34.7314536,
                        "lng" : 135.5001444
                     },
                     "travel_mode" : "DRIVING"
                  },
                  {
                     "distance" : {
                        "text" : "2.9 km",
                        "value" : 2945
                     },
                     "duration" : {
                        "text" : "3分",
                        "value" : 205
                     },
                     "end_location" : {
                        "lat" : 34.7025868,
                        "lng" : 135.5018373
                     },
                     "html_instructions" : "\u003cb\u003e新御堂筋\u003c/b\u003e/\u003cb\u003e国道423号線\u003c/b\u003e に入る",
                     "maneuver" : "merge",
                     "polyline" : {
                        "points" : "s}}rEcr_zX`@AjTGb@?^A^EzFg@f\\_DfHm@d@GtAGL?zQ?bBCjA?vCUjHm@bCS|DOHFlBNx@CdEBz@C`@Eb@Kl@U`@[fA{@d@_@f@Uj@Qb@E`@CfBKlBMjBI~@E"
                     },
                     "start_location" : {
                        "lat" : 34.7287408,
                        "lng" : 135.4987354
                     },
                     "travel_mode" : "DRIVING"
                  },
                  {
                     "distance" : {
                        "text" : "0.9 km",
                        "value" : 854
                     },
                     "duration" : {
                        "text" : "4分",
                        "value" : 220
                     },
                     "end_location" : {
                        "lat" : 34.6979391,
                        "lng" : 135.5062121
                     },
                     "html_instructions" : "\u003cb\u003e国道423号線\u003c/b\u003e を直進する",
                     "maneuver" : "straight",
                     "polyline" : {
                        "points" : "ezxrEoe`zXjBGH?jFKNCfAA|IMRAPELILKJQJ[DQ@MBe@D{BZoKDcBC_A"
                     },
                     "start_location" : {
                        "lat" : 34.7025868,
                        "lng" : 135.5018373
                     },
                     "travel_mode" : "DRIVING"
                  },
                  {
                     "distance" : {
                        "text" : "1.1 km",
                        "value" : 1083
                     },
                     "duration" : {
                        "text" : "4分",
                        "value" : 251
                     },
                     "end_location" : {
                        "lat" : 34.6971247,
                        "lng" : 135.518018
                     },
                     "html_instructions" : "\u003cb\u003e京阪国道\u003c/b\u003e/\u003cb\u003e国道1号線\u003c/b\u003e に入る",
                     "maneuver" : "merge",
                     "polyline" : {
                        "points" : "c}wrEy`azXJmCHmCHoCHmDDcAFqCFqCHiCJuCRmGFeCHkCBu@JcDBaBFwAJcD"
                     },
                     "start_location" : {
                        "lat" : 34.6979391,
                        "lng" : 135.5062121
                     },
                     "travel_mode" : "DRIVING"
                  },
                  {
                     "distance" : {
                        "text" : "1.3 km",
                        "value" : 1260
                     },
                     "duration" : {
                        "text" : "3分",
                        "value" : 171
                     },
                     "end_location" : {
                        "lat" : 34.6858388,
                        "lng" : 135.5174162
                     },
                     "html_instructions" : "\u003cb\u003e東天満（交差点）\u003c/b\u003e を\u003cb\u003e右折\u003c/b\u003eして \u003cb\u003e天満橋筋\u003c/b\u003e/\u003cb\u003e府道30号線\u003c/b\u003e に入る\u003cdiv style=\"font-size:0.9em\"\u003eそのまま 府道30号線 を進む\u003c/div\u003e",
                     "maneuver" : "turn-right",
                     "polyline" : {
                        "points" : "_xwrEsjczXZOdCHdBFh@DdADV@zALxANt@FnBRdBHj@D~CBrFF~K\\dCAfBA|A?r@AT?fCE"
                     },
                     "start_location" : {
                        "lat" : 34.6971247,
                        "lng" : 135.518018
                     },
                     "travel_mode" : "DRIVING"
                  },
                  {
                     "distance" : {
                        "text" : "0.3 km",
                        "value" : 311
                     },
                     "duration" : {
                        "text" : "1分",
                        "value" : 85
                     },
                     "end_location" : {
                        "lat" : 34.6856258,
                        "lng" : 135.5208023
                     },
                     "html_instructions" : "\u003cb\u003e谷町２（交差点）\u003c/b\u003e を\u003cb\u003e左折\u003c/b\u003eして \u003cb\u003e上町筋\u003c/b\u003e に向かう",
                     "maneuver" : "turn-left",
                     "polyline" : {
                        "points" : "oqurE{fczXFcADmBZqN"
                     },
                     "start_location" : {
                        "lat" : 34.6858388,
                        "lng" : 135.5174162
                     },
                     "travel_mode" : "DRIVING"
                  },
                  {
                     "distance" : {
                        "text" : "0.1 km",
                        "value" : 141
                     },
                     "duration" : {
                        "text" : "1分",
                        "value" : 36
                     },
                     "end_location" : {
                        "lat" : 34.6868503,
                        "lng" : 135.520398
                     },
                     "html_instructions" : "\u003cb\u003e府庁南（交差点）\u003c/b\u003e を\u003cb\u003e左折\u003c/b\u003eして \u003cb\u003e上町筋\u003c/b\u003e に入る\u003cdiv style=\"font-size:0.9em\"\u003e目的地は前方左側です\u003c/div\u003e",
                     "maneuver" : "turn-left",
                     "polyline" : {
                        "points" : "epurE_|czXsFnA"
                     },
                     "start_location" : {
                        "lat" : 34.6856258,
                        "lng" : 135.5208023
                     },
                     "travel_mode" : "DRIVING"
                  }
               ],
               "traffic_speed_entry" : [],
               "via_waypoint" : []
            }
         ],
         "overview_polyline" : {
            "points" : "ix~rEy{_zXScAFg@JQJE\\KL?PARD\\H^RXP`@h@~AnAtE~CbBbALJVHx@HpA@p@PlUIbAAzGm@ne@mEzBOxWCbMcAbCS|DOHFlBN~F?z@C`@Eb@Kl@UhBwAd@_@f@Uj@Qb@EhCOxEWjDMtFKNCfAApJOPELIX]Pm@f@_QDcBC_AT{G`@sOrAkd@JyDJcDZOjFPnBJbGf@tE\\jEHrFF~K\\lFCnHGLqDZqNsFnA"
         },
         "summary" : "国道423号線",
         "warnings" : [],
         "waypoint_order" : []
      }
   ],
   "status" : "OK"
}
```

ということで、使う場合は注意しましょう！

# 余談
国内の路線データAPIが軒並み有料なのにすごい！ と思ってウキウキだったのですが、世の中そんなに甘くないですね。
エンジニアの端くれとして、貴重なデータが安易に無料で使えないのは良いような悪いようなな気分ではあります。

ちなみにこの記事書く為に検索範囲を新大阪駅から大阪駅にして、 `transit` にして検索してみたところ、**なんと結果が返ってきました**。

ただし、バスと徒歩を駆使した経路になります。なんやそれ。
あくまで路線の検索は不可能、ということのようです。

以上です。