end0tknr's kipple - web写経開発

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

geocoding (住所→座標(緯度経度))変換は、google map apiより Yahoo!ジオコーダAPIがよさそ

yahoo apiの仕様の方が使いやすそう

google map api とゼンリン地図で geocoding (住所→座標(緯度経度)) - end0tknrのkipple - web写経開発
google map api ver.3でgeocoding - end0tknrのkipple - web写経開発

リクエスト数制限=2,500回/日のgmap apiと比較すると、yahooのapiは...

  • 利用制限 50,000回/日
  • 住所検索レベル( 1:都道府県、2:市町村、3:町・大字、4:丁目・字)を指定可能
  • 指定した住所レベルでマッチしなかった場合、上位のレベルで再検索

のように使用制限が緩やかっぽい.

http://developer.yahoo.co.jp/webapi/map/openlocalplatform/v1/geocoder.html
http://developer.yahoo.co.jp/appendix/rate.html

で、yahoo api版のジオコードを書くなら...

次の通り

#!/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;

#refer to :
#  http://developer.yahoo.co.jp/webapi/map/openlocalplatform/v1/geocoder.html
my $GEO_API =
    "http://geo.search.olp.yahooapis.jp/OpenLocalPlatform/V1/geoCoder";
my $APP_ID = 'appid=ないしょ';
#詳細はyahooのドキュメントを参照下さい
my $GEO_OPT = "output=json&al=3&ar=ge&recursive=true";

main(@ARGV);

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

    open(my $fh,"<:encoding(utf8)",$adrs_file) or die "can't open $adrs_file $!";
    my @adrs_orgs = <$fh>;
    close($fh) or die "can't close $adrs_file $!";

    for my $adrs_org ( @adrs_orgs ){
	chomp($adrs_org);
	my @cols = split(/\t/,$adrs_org);
	# if($cols[2]){
	#     print encode('utf8',$adrs_org),"\n";
	#     next;
	# }
        @cols[2..5] = geocode( $cols[1] );

	print encode('utf8', join("\t",@cols)),"\n";
#	sleep(1);
    }
}


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("$GEO_API?$APP_ID&$GEO_OPT&query=$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);
    unless($res->{ResultInfo}->{Count}){
        print STDERR encode('utf8', "geocode not found : $adrs_org\n");
        return undef;
    }

    my ($lng,$lat) = split(/,/,$res->{Feature}->[0]->{Geometry}->{Coordinates});

    return ($res->{Feature}->[0]->{Name},	#parsed address
	    $lat, $lng,				#経度, 緯度
	    $res->{Feature}->[0]->{Property}->{AddressMatchingLevel}); #変換精度
}

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;
}