what3wordsを使って住所を取得してみる

# what3wordsとは
地球を3m x 3mの57兆個の区画に分割し、その区画毎に3つの言葉を割り当てることで、場所を識別できるようにしたシステムです。（参考：[Wikipedia](https://ja.wikipedia.org/wiki/What3words)）



# what3wordsを使って住所取得してみる
私個人としては、what3wordsは日本での利用においてあまり大きなメリットを感じないのですが、流行ってくると、住所入力をwhat3wordsの3単語で行うということが普通になるかもしれません。今は、郵便番号を入力するとそれに対応する住所が自動で入力されますが、郵便番号の代わりに住所に対応する3単語を入力すると住所が自動で入力されるというイメージです。郵便番号に比べてwhat3wordsはより場所を正確に指定できるので、番地まで自動入力することが可能となります。また、数値での入力の場合、誤入力を検出することは難しいのですが、what3wordsの場合は、入力間違いを検出したり、入力候補を出したりすることが可能となります。ただ、日本では郵便番号というシステムが出来上がってしまっている以上、これにとって代わることは難しく、別の角度から浸透しないと流行ることはないと思いますが、興味本位でwhat3wordsとGoogleMapのAPIを使って住所取得してみることにしました。
## 仕組み
what3wordsのAPIを使って3単語を緯度経度情報に変換し、それをGoogleMapのAPIを使って住所に変換するという簡単なものです。
## 準備
- what3wordsのAPIキーの取得など

以下のサイトを参考にAPIキーを取得しました。また、APIの使い方なども参考にさせてもらいました。
[what3words APIを使ってみる](https://qiita.com/yodaaa/items/bf61a3812c1efc03f5d6)
ちなみに、このリンク先の記事ではv2のAPIを使っていますが、2019/9/1時点ではv3のAPIが最新なのでAPIをいろいろ試してみる場合はv3がおすすめです。

- GoogleMapsAPIのAPIキーの取得など

以下のサイトを参考にAPIキーを取得し、緯度経度から住所を取得する方法も参考にさせてもらいました。
[pythonでgoogle map apiを使って緯度経度から住所を取得](https://qiita.com/uni-3/items/56a1b033b54ea4be3f8d)

## コード

requestsとgooglemapsはあらかじめpipでインストールしておく必要があります。

```python
import os
import json
import requests
import googlemaps

API_ENDPOINT = 'https://api.what3words.com/v3/convert-to-coordinates'
MAP_ENDPOINT = 'https://maps.googleapis.com/maps/api/geocode/json'
WHAT3WORDS_API_KEY = os.environ.get('WHAT3WORDS_API_KEY')
MAP_API_KEY = os.environ.get('MAP_API_KEY')

    
def conv_3words2address(word1, word2, word3, lang='en'):
    coordinates = _get_coordinates(word1, word2, word3)
    address = _get_address(coordinates, lang)
    return json.dumps(_create_response(address))
    
def _get_coordinates(word1, word2, word3):
    params = {
        'words': f'{word1}.{word2}.{word3}',
        'key': WHAT3WORDS_API_KEY
    }
    response = requests.get(API_ENDPOINT, params=params)
    return response.json()

def _get_address(cordinates, lang):
    gmaps = googlemaps.Client(key=MAP_API_KEY)
    square = cordinates["square"]
    lng= (square["southwest"]["lng"] + square["northeast"]["lng"]) / 2
    lat = (square["southwest"]["lat"] + square["northeast"]["lat"]) / 2
    return gmaps.reverse_geocode((lat, lng), language=lang, location_type=["GEOMETRIC_CENTER"])

def _create_response(address):
    data = address[0]['address_components']
    return data
```
```
>>> conv_3words2address('hoge', 'hoge', 'hoge')
'[{"long_name": "Tenkerli K\\u00f6y\\u00fc Yolu", "short_name": "Tenkerli K\\u00f6y\\u00fc Yolu", "types": ["route"]}, {"long_name": "Tenkerli", "short_name": "Tenkerli", "types": ["administrative_area_level_4", "political"]}, {"long_name": "Feke", "short_name": "Feke", "types": ["administrative_area_level_2", "political"]}, {"long_name": "Adana", "short_name": "Adana", "types": ["administrative_area_level_1", "political"]}, {"long_name": "Turkey", "short_name": "TR", "types": ["country", "political"]}, {"long_name": "01660", "short_name": "01660", "types": ["postal_code"]}]'
```

上記のようにconv_3words2address(word1, word2, word3, lang='en')関数にwhat3wordsの3単語を入力すれば対応する住所のレスポンスが得られます。
_get_coordinates関数はwhat3wordsのAPIを使って緯度経度情報を取得しています。
_get_address関数はgoogle mapのAPIを使って緯度経度情報を住所に変更しています。
what3wordsのAPIは3m x 3mのボックスの情報を返すので、その中心の緯度経度に変換して住所を取得するようにしています。

というか、(hoge, hoge, hoge)に対応する住所がちゃんとあるんですね。。。

# 最後に
今回はwhat3wordsのAPIを少し触っただけですが、候補ワードを出すAPIや、検索できる地域を絞り込めるAPIなどいろいろあるので興味のある人はもっと触ってみると面白いかもしれません。

[what3words API v3](https://docs.what3words.com/api/v3/)
[googlemaps python client](https://googlemaps.github.io/google-maps-services-python/docs/)