Directions API(Google Maps Platform) をコールしてルート間の距離と所要時間をPythonで取得する 

#本投稿を書くきっかけ
自宅から行き先を調べるとき、行き先が１つの場合は Googleマップで入力すれば問題ないですが、
遊びにいく候補地(目的地)のリストがあって、自宅からの所要時間を調べるとき、
Googleマップでそれぞれの候補地の入力はしんどいので、もっと簡単にできないかというのがそもそもの背景です。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/261475/df3571b2-87b0-c44f-01e8-9830d9f8be27.png)

**Google Maps Platform Directions APIを使用した投稿は以下を参照ください。**
　[お父さん必見！週末お出かけ候補リストをかんたん作成(Python、Directions API)](https://qiita.com/kngsym2018/items/6664539b4fcd1d5f4cac)


<BR>
**本投稿では、Google Maps Platform の KEY申請方法、Directions APIの使用方法、Pythonを使ったサンプルについて記載しています**

**■Googleマップ**
　出発地、目的地を入力　※みんな知ってますが。。念のため
![image.png](https://qiita-image-store.s3.amazonaws.com/0/261475/95ba2e05-62eb-898e-1d90-d73bc9773783.png)

**■Directions API**
　以下のURLにリクエストします
![image.png](https://qiita-image-store.s3.amazonaws.com/0/261475/a1c86ddf-cb55-d8a8-8969-6c7cf08f1936.png)

実行サンプル
![image.png](https://qiita-image-store.s3.amazonaws.com/0/261475/16d7f26c-b9f2-377a-dfe9-9567cb653933.png)


　指定した出力形式(JSON or XML)で結果がかえります。
　以下の例ではJSONを指定した結果となります
![image.png](https://qiita-image-store.s3.amazonaws.com/0/261475/56c3f109-d731-1998-4e32-0d12fa583910.png)
返された情報(JSON or XML)から、距離や所要時間を取得することができます

#Directions API (Google Maps Platform)とは
Googleマップでルートや距離、所要時間などを検索する「ルート（Routes）」を 
API(Directions API)を使用して情報取得する方法です。

Directions APIを使用するには、
「Google Maps Platform」でAPIキーを取得しないと、Directions API その他のAPI は使用できません。
「Google Maps Platform」は3種類（Maps、Routes、Places）あります。 
 　※詳しくはこちらを参照ください
　　　https://cloud.google.com/maps-platform/?hl=ja

**・Maps**
　　マップの地図やストリートビューの情報を取得
  
**・Routes**
　　出発地点、到着地点を指定することでルートと所要時間を取得
　　**※Directions API　はここに所属**
  
**・Places**
　　指定した場所の周辺施設の情報を取得
 
  ※今回はその中にある、Routesにある、Directions APIについて投稿します




#事前準備　「Google Maps Platform」でAPIキーを取得

こちらは 2018年10月時点の情報になります

１．Google Maps Platform のページにアクセス
　　　https://cloud.google.com/maps-platform/

![image.png](https://qiita-image-store.s3.amazonaws.com/0/261475/bca9f768-cbbc-bcc8-a60c-521b30127bba.png)

２．ログイン
　
メールアドレスとパスワードを入力してログインします
![image.png](https://qiita-image-store.s3.amazonaws.com/0/261475/611f856c-6b58-420d-acf1-21717e180f46.png)


３．使用するPRODUCT を選択
Google Maps Platform で使用する機能を選択。今回はすべての機能を選択
![image.png](https://qiita-image-store.s3.amazonaws.com/0/261475/8b36232b-5177-275a-420b-47af2e2a7ae8.png)


４．プロジェクト名を入力
プロジェクト名はなんでもOK。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/261475/0bdffeff-b610-d8aa-ff60-e50cf840ff96.png)



５．請求先アカウントを作成
![image.png](https://qiita-image-store.s3.amazonaws.com/0/261475/f6289616-4eea-9283-e586-96d7dc0513fa.png)


６．請求先アカウントの詳細入力
![image.png](https://qiita-image-store.s3.amazonaws.com/0/261475/d79fb736-97d5-69a1-2f74-5d1c3434b1e9.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/261475/4061fae5-135f-23f7-9908-89d5de17eea1.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/261475/491924ee-1dfb-d242-4ae2-df2c6d774633.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/261475/6c77489c-c997-41ce-7eee-062d4072043d.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/261475/41a210d4-ce5a-2805-211e-3699fe1d9b4b.png)

このAPIキーを使用することで、Google Maps Platform Directions APIを使用できます。


登録したAPIアカウント情報は以下のURLから確認できます。
　https://console.developers.google.com/

APIを利用する際の料金は Directions / Directions Advanced(交通情報を考慮する)ですと
個人で触るぶんには無料枠内で十分です。
　https://cloud.google.com/maps-platform/pricing/sheet/?hl=ja
![image.png](https://qiita-image-store.s3.amazonaws.com/0/261475/aceec837-ffc4-07d2-4e8b-bf7c0bcee601.png)




#Directions APIの使用方法
  以下のURLにリクエストします

  ```https
  https://maps.googleapis.com/maps/api/directions/outputFormat?parameters
  ```

  **outputFomat**
    結果をJSONで受け取るか、XMLで受け取るかを指定します
    
  **parameters**
   最低限必要なパラメータは、「出発地(origin)」、「目的地(destination)」、「APIキー」になります

##Directions API実行例
東京駅からスカイツリーへ行く際の距離・時間をJSONで取得したい場合、
以下の書き方になります

```
URL:https://maps.googleapis.com/maps/api/directions/json?origin=東京駅&destination=スカイツリー&key=<APIキー>
``` 
      
上記例で指定したパラメータ
　outputFormat=json
　origin=東京駅
　destination=スカイツリー
　key={取得したAPI Key}

上記例での実行結果
![image.png](https://qiita-image-store.s3.amazonaws.com/0/261475/15042f25-fe20-b454-3bb0-50b1c9eb8ed3.png)

所要時間は
 [routes]-[legs:]-[duration:]-[text] に 格納されます。



JSONをパースして距離、所要時間を取得する流れになります。
**※Directions APIを使用した、距離と所要時間を取得する Pythonスクリプトのサンプルは本投稿の最後に記載してます**

　

##JSON結果をみる場合のおすすめ

おススメは、firefox での実行をおススメします。
理由は、Directions APIの結果がJSON形式にした場合、オブジェクト・配列単位で折りたたむことができ、情報確認する場合に便利だからです。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/261475/65f686b2-cf68-ccfa-1260-d009223e5d5a.png)


#Directions API　パラメータ説明
基本的なDirections APIパラメータと指定したら便利なパラメータを記載します。
その他のパラメータと詳細は以下ドキュメントを参照ください

■Developer Guide (Google Maps Platform Directions API)　
　https://developers.google.com/maps/documentation/directions/intro?hl=ja
　
　
##必須パラメータ
出発地、目的地、APIキーを設定

**origin**
  出発地点を指定
    
    例)
    地名 - 東京駅
    緯度経度 35.8592065,139.7665079
    
<BR>
**destination**
  到着地点を指定
    
    例)
    地名 - 東京駅
    緯度経度 35.8592065,139.7665079

<BR>
**APIキー**
  取得したAPI Keyを指定


##その他パラメータ

**mode**

     例)
     driving - 車 ※デフォルト
     walking - 徒歩
     transit - 電車
     
     ※但し、日本は電車のサービスはなし 
     https://developers.google.com/maps/faq#transit_directions_countries
    

<BR>
**departure_time**

     出発時間を設定。設定はUNIX時間する。
     mode=drivingの場合に設定でき、現在時刻以降を設定する。※過去時間は設定NGです(結果が空白になります)
     ※現在時刻を設定する場合は、UNIX時間を設定でもできますが、「departure_time=now」 でも現在時刻が設定されます
     
     UNIX時間とは、
     協定世界時 (UTC) での1970年1月1日午前0時0分0秒から形式的な経過秒数（すなわち、実質的な経過秒数から、
     その間に挿入された閏秒を引き、削除された閏秒を加えたもの）
     
     参照
     =====
      https://ja.wikipedia.org/wiki/UNIX%E6%99%82%E9%96%93
     =====
     
     ⇒departure_timeは now or UNIX時間で設定。

departure_timeを設定すると、
交通状況を考慮した所要時間は
 [routes]-[legs:]-[trafic_in_duration:]-[text] に 格納されます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/261475/46f4b2c5-ef5c-e58e-47e7-bcba6476cc67.png)

**traffic_model**
        
    交通状態を考慮した時間算出方法を選択
    ※departure_time が設定された場合に有効になるパラメータになります
        
    best_guess ※デフォルト
      正確に予測
      ⇒リクエストされた時刻や曜日に関連する過去のデータやリアルタイムの交通状況に基づいて、最適な移動時間が算出されます。
     
    optimistic
      楽観的に予測
        
    pessimistic
      悲観的に予測

楽観的、悲観的についてのユースケースは、以下のドキュメントの説明がわかりやすい
　https://developers-jp.googleblog.com/2015/11/google-maps-apis.html


＞米国で不動産情報サイトを運営する Redfin 社では、不動産仲介業者が複数の物件の間を車で移動する際の所要時間の推定を
＞Google Maps Distance Matrix API を利用して実現しようとしています。
＞物件間の移動時間は十分余裕があることが望ましいので、ここでは pessimistic と設定します。
＞一方、遠隔地から自宅のエアコンを制御するアプリケーションでは、
＞帰宅するまでの間に部屋の温度が設定値となるように調整したいと考えるでしょうから、この場合は、optimistic に設定します。

通常は、「best_guess」でよさそうです。


##交通状況を考慮したルート選択
Google Maps Platform Directions API で最低限必要なパラメータ(origin、destination、key)を設定したものでは、交通量を考慮したルート選択をしていません。


■10/8 23:00 での Googleマップ とDirections API (Google Maps Platform)の実行結果の違い
![image.png](https://qiita-image-store.s3.amazonaws.com/0/261475/07c95b91-36d8-b6e3-ccd7-85e49cc933f1.png)



Googleマップでは出発時間が「すぐに出発」となっており、深夜だから通常よりも交通量が減るため
所要時間が少なくなっていると考えられます。


Directions APIで交通状況を考慮する、「departure_time」パラメータを設定して実行※departure_timeは now と設定して、Google マップの結果と比較してみる
![image.png](https://qiita-image-store.s3.amazonaws.com/0/261475/eec3f0af-cb12-a5ec-3718-a70e1047de8c.png)


所要時間は１８分となり、Googleマップの所要時間と一致。
(departure_timeを設定すると、交通状況を考慮した所要時間は、
 [routes]-[legs:]-[trafic_in_duration:]-[text] に 格納されます)


⇒所要時間を算出する場合は、交通状況を考慮する departure_time　を設定するほうがよさそうです。但し、交通状況を考慮する場合、Directions Advenced になるので、毎月の無料呼び出し数が40,000 ⇒ 20,000 になります ※個人で使用なので影響はありませんが

https://cloud.google.com/maps-platform/pricing/sheet/?hl=ja

　
#Pythonスクリプトで実行して、Directions API (Google Maps Platform)をコールして経過時間を取得してみる

```python:DirectionsAPI.py


import urllib.request, json
import urllib.parse
import datetime

#Google Maps Platform Directions API endpoint
endpoint = 'https://maps.googleapis.com/maps/api/directions/json?'
api_key = '<取得したAPIキー>'

#出発地、目的地を入力
origin = input('出発地を入力: ').replace(' ','+')
destination = input('目的地を入力: ').replace(' ','+')
dep_time = input('出発時間を入力: yyyy/mm/dd hh:mm 形式 ')

#UNIX時間の算出
dtime = datetime.datetime.strptime(dep_time, '%Y/%m/%d %H:%M')
#dtime = dtime + datetime.timedelta(hours=9)
#print(dtime.timestamp())
unix_time = int(dtime.timestamp())

print('')
print('=====')
print('unixtime')
print(unix_time)
print('=====')

nav_request = 'language=ja&origin={}&destination={}&departure_time={}&key={}'.format(origin,destination,unix_time,api_key)
nav_request = urllib.parse.quote_plus(nav_request, safe='=&')
request = endpoint + nav_request

print('')
print('=====')
print('url')
print(request)
print('=====')

#Google Maps Platform Directions APIを実行
response = urllib.request.urlopen(request).read()

#結果(JSON)を取得
directions = json.loads(response)

#所要時間を取得
for key in directions['routes']:
    #print(key) # titleのみ参照
    #print(key['legs']) 
    for key2 in key['legs']:
        print('')
        print('=====')
        print(key2['distance']['text'])
        print(key2['duration_in_traffic']['text'])
        print('=====')

```
[Pythonスクリプトの実行方法は Windows環境でPythonスクリプト(.py)の実行方法](https://qiita.com/kngsym2018/items/21b6efe4547a78661951) を参考ください。

#Pythonスクリプト実行結果



```
C:\Users\kngsym> python D:\phyton\DirectionsAPI.py
出発地を入力: 東京駅
目的地を入力: スカイツリー
出発時間を入力: yyyy/mm/dd hh:hh 形式 2018/10/08 23:40

=====
unixtime
1539009600
=====

=====
url
https://maps.googleapis.com/maps/api/directions/json?language=ja&origin=%E6%9D%B
1%E4%BA%AC%E9%A7%85&destination=%E3%82%B9%E3%82%AB%E3%82%A4%E3%83%84%E3%83%AA%E3
%83%BC&departure_time=1539009600&key=<ここは省略>
=====

=====
8.4 km
18分
=====
C:\Users\kngsym>
```

Googleマップの距離、所要時間と一致（距離：8.4km、所要時間：１８分）したし、Directions API からの結果も正常も取得できた！

#参考
Google Maps Platform Directions APIを使用したPythonコードは以下を参照させて頂きました
　https://www.youtube.com/watch?v=UrrWxyq1Z48
　https://githubja.com/googlemaps/google-maps-services-python

こちらは、Directions API (Google Maps Platform) を使用した投稿となります
[お父さん必見！週末お出かけ候補リストをかんたん作成(Python、Directions API)](https://qiita.com/kngsym2018/items/6664539b4fcd1d5f4cac)