PythonでDirections API(Google Maps Platform)を叩いてみた話

たくさんの住所のペアに対してその距離がどれくらいか知りたくなること、ありますよね。僕はありました。今回はDirections APIというものをPythonを使ってExcelにその結果を記録するまでの流れを書いていきます。

# API keyを取得する
<p>まずはAPI Keyを取得します。
<a href="https://developers.google.com/maps/documentation/directions/start?hl=ja#console">こちらのスタートガイド</a>に従ってプロジェクトをセットアップしていきましょう。途中で支払い手段の登録をすることになりますが、<b>登録後90日間は300ドル相当のクレジットが使えますし、月々の無料枠も200ドル存在します。</b> 詳しくは料金体系を調べてもらうとして、個人で使う分にはそんなに気にする必要はないと思います。


# リクエストに必要なもの

APIを叩くのに必要なアイテムは以下の通りです。
1. 出発地点(origin)
2. 目的地(destination)
3. APIキー(key)

ほかにもパラメータを増やすことが可能ではありますが、最低限これだけあれば2地点間の距離を取ってくることができます。

# リクエスト方法
Directions APIへのアクセスは以下の形式で行われます
```
https://maps.googleapis.com/maps/api/directions/outputFormat?parameters
```
outputFormatでは結果をXMLで受け取るかJSONで受け取るかを指定できます。今回はJSONを指定することにします。
parametersには先ほど紹介した必須アイテムをパラメータとして入れ込みます。

例えば皇居から国会議事堂までの距離を知るためのアクセス形式は以下のようになります。
```
https://maps.googleapis.com/maps/api/directions/json?origin=東京都千代田区千代田1-1&東京都千代田区永田町1-7-1&key=yourkey
```

今回は住所を直接入れていますが、住所を建物の名前で置き換えてもリクエストが通るのでお好きな方をお選びください。

APIを叩くとたくさんのデータが返ってきます。ターミナルが一瞬で埋め尽くされたりもするので興味のある方はやってみると面白いかもしれません。今回は欲しいデータが「距離」と分かっているので、直接そこにアクセスをしてデータを取得します。
距離のデータは **JSONの[routes][legs][distance][text]** に収納されています。


# 実際にAPIを取得するコードを書く
今回は皇居から
* 新宿御苑
* 国会議事堂
* スカイツリー
* 志摩スペイン村
* 新潟競馬場
への距離を取得してみましょう
実際に使用したコードが以下の通りです。
```py
import urllib
import urllib.error
import urllib.request
import json
import openpyxl


def main():
    endpoint = "https://maps.googleapis.com/maps/api/directions/json?"
    googleapikey = "Your API Key"
    record = []
    data_start_row = 2
    data_end_row = 7 #2行目から6行目にかけてデータが入っていることを示す
    for i in range(data_start_row, data_end_row):
        result = fetchData(endpoint, googleapikey, i)
        if result is not None:
            record.append(result)
    writeDown(record)


def fetchData(endpoint, googleapikey, row):
    place = fetchPlaceData(row)
    origin = "東京都千代田区千代田1-1"
    nav_request = "language=ja&origin={}&destination={}&key={}".format(
        origin, place.address, googleapikey
    )
    nav_request = urllib.parse.quote_plus(nav_request, safe="=&")
    request = endpoint + nav_request
    response = urllib.request.urlopen(request).read()
    directions = json.loads(response)
    tmpDist = ""
    for key in directions["routes"]:
        for key2 in key["legs"]:
            tmpDist = key2["distance"]["text"]
            break

    if tmpDist == None or tmpDist == "":
        return None

    place.dist = float((tmpDist[:len(tmpDist) - 3]).replace(",", ""))
    return place


def fetchPlaceData(row):
    path = "/path/to/hoge.xlsx"
    book = openpyxl.load_workbook(path)
    sheet = book["Sheet1"]
    book.close()
    #場所の名前がB行、住所がC行に入っている
    return PlaceData(sheet["B" + str(row)].value, sheet["C" + str(row)].value)


class PlaceData:#場所の名前と住所、距離を持つクラス
    name = None
    address = None
    dist = None

    def __init__(self, name, address):
        self.name = name
        self.address = address
        self.dist = None


def writeDown(result):
    path = "/path/to/fuga.xlsx"
    book = openpyxl.load_workbook(path)
    sheet = book["Sheet1"]
    row = 2
    for place in result:
        sheet["B" + str(row)].value = place.name
        sheet["C" + str(row)].value = place.address
        sheet["D" + str(row)].value = place.dist
        row += 1
        book.save(path)
    book.close()


main()
```

実際にこのコードを実行すると
![スクリーンショット 2023-06-28 184548.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631105/1ef2aaed-7145-dda6-cab8-818d1a965476.png)
こんな感じでデータを記録することができます。


# 参考文献
https://qiita.com/kngsym2018/items/15f19a88ea37c1cd3646