end0tknr's kipple - web写経開発

太宰府天満宮の狛犬って、妙にカワイイ

google map api ver.3でgeocoding

2013/11/23追記

この当時は、google map apiにお世話になりましたが、Yahoo!ジオコーダAPI もいい感じです。
geocoding (住所→座標(緯度経度))変換は、google map apiより Yahoo!ジオコーダAPIがよさそ - end0tknrのkipple - web写経開発


http://code.google.com/intl/ja/apis/maps/documentation/geocoding/

google map apiがversion 3になり、api keyが不要になったり、request数の制限が2500req/day になっていたので、以前、書いた住所→緯度経度の変換を行うperl scriptを書きなおしてみました。

#!/usr/local/bin/perl
use strict;
use utf8;
use Encode;
use JSON;
use LWP::UserAgent;
use Lingua::JA::Regular::Unicode qw/alnum_z2h/;
use Data::Dumper;

#ex. http://maps.google.com/maps/api/geocode/json
#       ?sensor=false&region=jp&address=東京都渋谷区渋谷 (url encoding)
my $GMAP_API = "http://maps.google.com/maps/api/geocode/json";
my $GMAP_API_OPT = "sensor=false&region=jp&language=ja";
# refer to  http://code.google.com/intl/ja/apis/maps/documentation/geocoding/
# sensor: ↑こちらをご覧ください
# region: 検索範囲を日本に限定
# language: gmap apiからのresponseを日本語に

main(@ARGV);

sub main {
    my ($address_file) = @_;

    open (my $fh,"<:utf8", $address_file) or
	 die "can't open file:$address_file:$!";
    my @adrs_lines = <$fh>;
    close($fh) or die "can't open file:$address_file:$!";

    my $i = 0;
    for my $adrs ( @adrs_lines ){
	$adrs =~ s/\s+$//go;
        my ($adrs_new,$lat,$lon,$accurate) = geocode( $adrs );
        print encode('utf8',
		     join("\t",$adrs,$adrs_new,$lat,$lon,$accurate)),"\n";
    }
}


sub geocode {
    my ($adrs_org) = @_;

    my $ua  = LWP::UserAgent->new();
    $adrs_org = conv_address($adrs_org);
    my $adrs_url_enc = url_encode($adrs_org);   #住所はurl encoding要

    my $res = $ua->get("$GMAP_API?$GMAP_API_OPT&address=$adrs_url_enc");
    unless ( $res->is_success ){
        print STDERR encode('utf8',"fail http get:$adrs_org\n");
        return undef;
    }

    my $res = decode_json($res->content);
    if ($res->{status} ne 'OK'){
        print STDERR encode('utf8',"fail gmap geocode:$adrs_org\n");
        return undef;
    }
    #geocoding結果が複数返るケースがあるらしい
    my $results = $res->{results};
    if (ref($results) ne "ARRAY" or @$results != 1){
        print STDERR encode('utf8',"gmap api multi results:$adrs_org\n");
        return undef;
    }

    return ($results->[0]->{formatted_address},   #parsed address
            $results->[0]->{geometry}->{location}->{lat}, #緯度
            $results->[0]->{geometry}->{location}->{lng}, #経度
            $results->[0]->{types}->[0]);	#変換精度
}

sub url_encode {
    my ($str) = @_;
    $str =~ s/(\W)/'%' . unpack('H2', $1)/ego;
    return $str;
}

sub conv_address {
    my ($adrs) = @_;
    $adrs = alnum_z2h($adrs);	#半角→全角
    #「、」で複数の住所を入力している場合、先頭の住所のみを有効とします
    $adrs =~ s/.+$//go;
    #ハイフン(-)の入力方法によって、geocodingに失敗するケースがあるようです
    $adrs =~ s/[\−─ー−]/\-/go;
    return $adrs;
}