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

  • 70
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

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

やりたい事

GoogleのGeocodingであったりYahoo!のジオコーダAPIを用いれば、住所の表記ゆれにも対応したよりスマートな緯度経度取得が可能ですが、利用数の制限や規約があるのが不便です。

もっと何度でも繰り返し自由に使える環境が欲しい!ということで本記事の内容となります。
「市区町村番地から緯度経度」ではなく、「緯度経度から市区町村番地」を取得する格好いいやり方は、masuidrive様の素晴らしく参考になる記事を参考下さい。

国土交通省のデータを使って、緯度経度から市区町村までを取り出す - Qiita

サマリ

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

データ取得

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

位置参照サービス.png

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

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

ダウンロード結果
  % 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のインストールはこのあたりを参考に。
格納先のテーブルは以下の形式としています。
(ジオグラフィー型とか知らない!)

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 が使えない時

処理対象を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を作成。

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を実行します。
ファイルパスとそれぞれの取り込み件数が表示されます。

実行結果

# 取り込み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万件とか結構な件数になってます。

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

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

緯度経度結果
=# 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=北海道四条通20丁目
giocoding.png

…合ってますね!

まとめ

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