Google Maps APIのGeocoding APIの番地取得処理を見直そう

# はじめに
[前回の記事](https://qiita.com/Kanno-san/items/689b463a030199c928cf,ジオコード)では、ジオコーディング時に変換前の住所と変換後の座標についてくる住所データを比較し精度のチェックをしました。
今回の記事では、残課題になっている変換後の住所で番地表記がブレる課題の対策をしていきます。

# 背景と目的
## 背景（再掲）
当社ではガスや灯油の個人宅への配送を支援するサービスを提供しています。
そのサービスの中に配送順を算出する機能がありますが、とりわけ重要となるのが個人宅の座標取得（ジオコーディング）となります。
座標がずれると「おかしな配送順序になる」、「ナビアプリへ連携したときに変なところに案内される」などの問題が発生します。

### 課題
座標の精度チェックの場合に以下の挙動が発生し、比較に失敗する場合がありました。
+ ○丁目－△の様に丁目や小字の後にハイフンが入ってしまう
+ 〇〇△△の様に番地がくっつく

## 目的
前述の課題を回避するため、比較用住所の構築のロジックの見直します。

### やること
+ GeoCoding APIの結果からパターン分けを行い、比較用として望ましい住所表記に変換する

## 事前準備（おさらい含む）
### Google Maps Geocoding APIの挙動の確認と対策
付帯情報の住所は引き続き、以下のサイトを参考にしています。
https://maps.multisoup.co.jp/blog/1952/

今回、処理の見直しを行う際に参照するデータは以下の通りとなります。
+ sublocality_level_3： 小字・丁目情報。
+ sublocality_level_4： 街区情報。番地の情報で〇〇－△△の〇〇だけが返ってくる場合がある。
+ premise：地番、枝番情報。番地情報で〇〇－△△が基本的には入る。たまに△△だけが返ってくる。

API実行結果で番地を取得しようとすると、sublocality_level_4の有無によってハイフンが入ったり入らなかったりで表記がぶれます。
このあたりはGeocoding APIで統一されていないところなので、まだなにか潜んでいる可能性があります。
まずは今回はこれの対策に焦点を絞ります。
+ sublocality3に「丁目」が含まれる かつ sublocality4がブランクでない場合、丁目の後に番地が入るのでハイフンを入れない
+ sublocality3がブランク かつ subllocality4がブランクでない場合、小字の後に番地が入るのでハイフンを入れる

## 対処
以降はPythonでの初期を記載していきます。

### 比較用住所の住所作成の見直し
前回作成した処理の一部を見直していきます。
こちらの処理が今回の実装と条件が異なっているので、見直していきます。

この条件の場合…
丁目がある場合に、番地との間にハイフンをいれます。sublocality4がブランクの場合に丁目－〇〇となります。
また、sublocality3に丁目が入っておらず、sublocality4とpremiseもブランク出ない場合に〇〇△△となります。
こちらのケースは考慮漏れです。

```python:前回のコード
# 郡の有無でパターン分け、sublocality4は無条件でいれる
result_address_include_admin2 = administrative_area2 + locality + sublocality1 + sublocality2 + sublocality3 + sublocality4
result_address_exclude_admin2 = locality + sublocality1 + sublocality2 + sublocality3 + sublocality4

# 丁目の有無と、番地の有無でハイフンをつけるか判断
if premise != '':
    if '丁目' in sublocality3 or (sublocality3 == '' and sublocality4 != ''):
        support_hyphen = '－'
    result_full_address_include_admin2 = result_address_include_admin2 + support_hyphen + premise
    result_full_address_exclude_admin2 = result_address_exclude_admin2 + support_hyphen + premise
```

新しい条件の場合…
丁目が含まれる場合でsublocality4がブランクでない場合は、丁目〇〇-△△となります。
また、sublocality3がブランクの場合でsublocality4がブランク出ない場合に小字〇〇-△△となります。
間違い探しのような修正ですね（カッコの位置だけ）
元からの不具合っぽい感じに見えますが、本当に考慮漏れ＆実装上のラッキーヒットです。

```python:修正のコード
# 郡の有無でパターン分け、sublocality4は無条件でいれる
result_address_include_admin2 = administrative_area2 + locality + sublocality1 + sublocality2 + sublocality3 + sublocality4
result_address_exclude_admin2 = locality + sublocality1 + sublocality2 + sublocality3 + sublocality4

# 丁目の有無もしくはsublocality3の有無と、sublocality4の有無でハイフンの有無を判断
if premise != '':
    if ('丁目' in sublocality3 or sublocality3 == '') and sublocality4 != '':
        support_hyphen = '－'
    result_full_address_include_admin2 = result_address_include_admin2 + support_hyphen + premise
    result_full_address_exclude_admin2 = result_address_exclude_admin2 + support_hyphen + premise
```

## 今後の課題
今回の修正で番地の表記がブレる事象は修正できました。
一方で、まだ遭遇していないAPIの実行結果がある可能性を危惧しています。
そのようなものが出てきた場合には、引き続き対策をご紹介できればと考えています。

以下が残課題です。

### 表記ゆれ（再掲）
住所入力を人手で行っている限り常に発生する課題となります。
よくあるものだと「が」「ヶ」「ケ」がわかり易い例ですね。
ある程度はパターン登録でできるか？とか考えた時期もありましたが、茅ヶ崎市と横浜市都筑区茅ケ崎町のようなパターンが出てきて頭を抱えました。
これの対策には文字列の類似度を測る処理をいれ、大凡一致していたらOKとするような処理にしようかなと画策しています。
参考URL： http://pixelbeat.jp/text-matching-3-approach-with-python/

結構、重いので次回更新までに実装できれば紹介したいなと考えています。

# まとめ
ジオコーディング時の精度チェックのための住所比較の更新を行いました。
本手法を用いることで、座標取得の処理精度が最大1割程度向上しました。
依然として、表記ゆれであったり、API実行結果に依存するものが残っていますが、今後も引き続き改善を行い、その手法を共有できたらいいなと考えています。