概要
最近、帰宅報告なんかを色々なサービス使って作ってる記事が多いじゃないですか。
そういうのの一環で、帰宅報告のついでに帰宅予想時間とか書けると面白そうじゃないかと考えてみたわけですよ。
今から帰ります!
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キーが必要です。
上記説明ページ内のキーの取得
をクリックしますが、プロジェクト選べ、となります。
Googleの環境にプロジェクトがないと使わせてくれないようです。
+ Create a new project
を選択して適当にプロジェクト名を入力します。
NEXT
を押すと作成処理が開始、APIキーが生成されます。
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で結果が返ってきます。こんなの。
{
"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でサンプル作ってみたわけですよ。
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}®ion={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
これで、
src = MapCoordinate(34.733165, 135.500214) # 新大阪駅
dest = MapCoordinate(34.686669, 135.519586) # 大阪府庁舎
route = MapRoute(src, dest, MapRoute.mode_transit)
direction_json = getGoogleMapDirection(route)
みたいにして、取得したところ、、、
{
"available_travel_modes" : [ "DRIVING", "WALKING" ],
"geocoded_waypoints" : [ {}, {} ],
"routes" : [],
"status" : "ZERO_RESULTS"
}
??なんやこの結果?? と思って調べてみたら。
The Google Maps Directions Service supports all of the transit providers listed in the Transit Coverage List, except for those in Japan.
!?
Google マップのルートサービスでは、交通機関の対象リストに記載されているすべての交通機関(日本を除く)をサポートしています。
なんてこった日本。
何かしらのパワーを感じるぜ、、、
ということで、日本で使用できるのは walking
と driving
の2モードのみのようです。
上記の処理を MapRoute.mode_driving
にすると無事結果が返ってきました!
{
"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, 5丁目-16 西中島 淀川区 大阪市 大阪府 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谷町2(交差点)\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
にして検索してみたところ、なんと結果が返ってきました。
ただし、バスと徒歩を駆使した経路になります。なんやそれ。
あくまで路線の検索は不可能、ということのようです。
以上です。