住所（市区町村番地）から緯度経度を取得する

関連して以下も参考にしてください

> * [初めて地図周りの技術に触れた時に作ったまとめ資料 - Qiita] (http://qiita.com/laqiiz/items/7d256108920ff7afbf08)
* [GoogleMapのオープンソース版地図アプリ（OSRM）のインストール - Qiita](http://qiita.com/laqiiz/items/e188b0d5d21fe7aa0de7)

# やりたい事

Googleの[Geocoding](http://www.geocoding.jp/)であったりYahoo!の[ジオコーダAPI](http://developer.yahoo.co.jp/webapi/map/openlocalplatform/v1/geocoder.html)を用いれば、住所の表記ゆれにも対応したよりスマートな緯度経度取得が可能ですが、利用数の制限や規約があるのが不便です。

もっと何度でも繰り返し自由に使える環境が欲しい！ということで本記事の内容となります。
「市区町村番地から緯度経度」ではなく、「緯度経度から市区町村番地」を取得する格好いいやり方は、masuidrive様の素晴らしく参考になる記事を参考下さい。
> [国土交通省のデータを使って、緯度経度から市区町村までを取り出す - Qiita](http://qiita.com/masuidrive/items/21a282c7bf54fd6a4985)

# サマリ

0. データ取得
0. PostgreSQLに突っ込む
0. 動作確認

# データ取得

[位置参照情報ダウンロードサービスについて](http://nlftp.mlit.go.jp/isj/)からデータ取得
国土交通省が出してくれているデータです。
2014年ころから町丁目レベルのデータを提供してくれているそうです。

![位置参照サービス.png](https://qiita-image-store.s3.amazonaws.com/0/6463/647c0be2-977e-388d-8550-80c7593363c5.png)

「位置参照情報ダウンロードサービスへ」のリンクをクリック
　→「都道府県選択」のリンクをクリック
　　→「全ての都道府県を選択」
　　　→「街区レベル」を選択してそれぞれポチポチDL

(※)都道府県ごとにポチポチするので時間かかります‥。

> ```shell:ダウンロード結果
  % ls                                                                                    
01000-12.0a.zip  09000-12.0a.zip  17000-12.0a.zip  25000-12.0a.zip  33000-12.0a.zip  41000-12.0a.zip
02000-12.0a.zip  10000-12.0a.zip  18000-12.0a.zip  26000-12.0a.zip  34000-12.0a.zip  42000-12.0a.zip
03000-12.0a.zip  11000-12.0a.zip  19000-12.0a.zip  27000-12.0a.zip  35000-12.0a.zip  43000-12.0a.zip
04000-12.0a.zip  12000-12.0a.zip  20000-12.0a.zip  28000-12.0a.zip  36000-12.0a.zip  44000-12.0a.zip
05000-12.0a.zip  13000-12.0a.zip  21000-12.0a.zip  29000-12.0a.zip  37000-12.0a.zip  45000-12.0a.zip
06000-12.0a.zip  14000-12.0a.zip  22000-12.0a.zip  30000-12.0a.zip  38000-12.0a.zip  46000-12.0a.zip
07000-12.0a.zip  15000-12.0a.zip  23000-12.0a.zip  31000-12.0a.zip  39000-12.0a.zip  47000-12.0a.zip
08000-12.0a.zip  16000-12.0a.zip  24000-12.0a.zip  32000-12.0a.zip  40000-12.0a.zip
 ```

# データ構造

以下で定義されています。
http://nlftp.mlit.go.jp/isj/data.html

# PostgreSQLに突っ込む

 PostgreSQLのインストールはこの[あたり](http://blog.scimpr.com/2012/09/01/ubuntu12-04%E3%81%A7postgresql%E3%82%92%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%81%99%E3%82%8B/)を参考に。
 格納先のテーブルは以下の形式としています。
 （ジオグラフィー型とか知らない！） 
 
 >```sql:create文
 >create table m_address_gaiku (
 >    prefectures_nm    varchar(4),
 >    city_nm           varchar(10),
 >    oaza_nm                varchar(20),
 >    block_no	          varchar(15),
 >    coordinate_no   numeric(3),
 >    x_coordinate		numeric(8, 1),
 >    y_coordinate		numeric(8,1 ),
 >    latitude			 varchar(15),
 >    longitude			 varchar(15),
 >    displayed_address_flg			char(1),
 >    representative_flg	char(1),
 >    before_history_flg	char(1),
 >    after_history_flg	char(1)
 >);
 >```
 

先ほどダウンロードしたZIPファイルを解凍して、格納されているCSVファイルをPostgreSQLに読み込ませます
Copyコマンドを用いるので、ユーザ権限をSuperUserにしておく必要があります。
> [参考情報 - PostgreSQL で COPY が使えない時](http://bmath.org/wordpress/?p=1427)

```sh:処理対象をCSVに抽出
# 解凍
find ./ -name "*.zip" -type f -print0 | xargs -0 -I {} unzip {} 

# 対象のCSV一覧を出力
find ./ -name "*.csv" -type f -print0 | xargs -0 -I {}  echo `pwd`/{} > list.txt

```

Copyコマンド実行用のshellを作成。

```sh:copy.sh
#!/bin/sh

# copyコマンド作成
cd `dirname $0`
cat list.txt | while read file; do
echo $file
psql gis << EOF
        COPY m_address_gaiku (
    	    prefectures_nm,
            city_nm,
        	oaza_nm,
        	block_no,
        	coordinate_no,
        	x_coordinate,
	        y_coordinate,
	        latitude,
	        longitude,
	        displayed_address_flg,
	        representative_flg,
	        before_history_flg,
	        after_history_flg
        )
        FROM
            '$file'
        WITH
        (
	        format		csv,
        	header		true,
        	delimiter	',',
        	quote		'"',
	        encoding	'Shift-JIS'
        );
EOF
done
```

先ほど作成した```copy.sh```を実行します。
ファイルパスとそれぞれの取り込み件数が表示されます。

```sh:実行結果

# 取り込みshellの実行
% sh copy.sh

# 実行結果
/home/mano/postgis/data/./38000-12.0a/38_2013.csv
COPY 202088
/home/mano/postgis/data/./41000-12.0a/41_2013.csv
COPY 101563
/home/mano/postgis/data/./02000-12.0a/02_2013.csv
COPY 136475
#・・・以下略・・・
```

# 動作確認

969万件とか結構な件数になってます。

```sql:結果件数
=# select count(*) from m_address_gaiku;
  count  
---------
 9696619
(1 row)
```

肝心の中身チェック。
「北海道の旭川四条通20丁目」の緯度経度を調べてみる。
```prefectures```や```city```や```area```カラムそれぞれにバインドする必要があります。

```sql:緯度経度結果
=# select prefectures_nm, city_nm, oaza_nm, block_no, latitude, longitude  from m_address_gaiku where prefectures_nm= '北海道' and city_nm= '旭川市' and oaza_nm like '四条通二十丁%';

prefectures_nm|  city_nm|      oaza_nm      | block_no | latitude  | longitude  
-------------+--------+----------------+------------+-----------+------------
 北海道      | 旭川市 | 四条通二十丁目 | 1720       | 43.763105 | 142.379743
 北海道      | 旭川市 | 四条通二十丁目 | 右5        | 43.763105 | 142.379743
 北海道      | 旭川市 | 四条通二十丁目 | 9          | 43.763105 | 142.379743
 北海道      | 旭川市 | 四条通二十丁目 | 右10       | 43.763105 | 142.379743
 北海道      | 旭川市 | 四条通二十丁目 | 1717       | 43.763671 | 142.380069
 北海道      | 旭川市 | 四条通二十丁目 | 4          | 43.763671 | 142.380069
 北海道      | 旭川市 | 四条通二十丁目 | 左9        | 43.763671 | 142.380069
 北海道      | 旭川市 | 四条通二十丁目 | 左6        | 43.763671 | 142.380069
 北海道      | 旭川市 | 四条通二十丁目 | 左5        | 43.763671 | 142.380069
 北海道      | 旭川市 | 四条通二十丁目 | 左2        | 43.763671 | 142.380069
 北海道      | 旭川市 | 四条通二十丁目 | 左4        | 43.763671 | 142.380069
```

このクエリ結果をgiocoding結果と比べてみると…
[www.geocoding.jp/?q=北海道四条通２０丁目](http://www.geocoding.jp/?q=%E5%8C%97%E6%B5%B7%E9%81%93%E5%9B%9B%E6%9D%A1%E9%80%9A%EF%BC%92%EF%BC%90%E4%B8%81%E7%9B%AE)
![giocoding.png](https://qiita-image-store.s3.amazonaws.com/0/6463/c992a2be-cd6f-f4c7-9176-f286c8d088b3.png)

…合ってますね！


# まとめ

* 住所の揺れさえ無視できる環境であれば緯度・経度を取得できる！
* 住所から緯度経度を大量件数引き当てたい時を除けば、とても賢いgiocodingかジオコーダAPIを使いたい！