3

In Perl how do get the lat and long from an arbitrary address? It is OK to use an external API.

jpgunter
  • 502
  • 4
  • 10

3 Answers3

3

Here is a quick perl function to get the latitude and longitude of an arbitrary address. It uses LWP::Simple and JSON from CPAN and Google's Geocode API. You can do either json or xml if you want the full data, this one use's json and just grabs and returns the lat and long.

use strict;
use LWP::Simple; # from CPAN
use JSON qw( decode_json ); # from CPAN

sub getLatLong($){
  my ($address) = @_;

  my $format = "json"; #can also to 'xml'

  my $geocodeapi = "https://maps.googleapis.com/maps/api/geocode/";

  my $url = $geocodeapi . $format . "?sensor=false&address=" . $address;

  my $json = get($url);

  my $d_json = decode_json( $json );

  my $lat = $d_json->{results}->[0]->{geometry}->{location}->{lat};
  my $lng = $d_json->{results}->[0]->{geometry}->{location}->{lng};

  return ($lat, $lng);
}
jpgunter
  • 502
  • 4
  • 10
  • 1
    So you answered your own question in just 1 minute? :) – Chankey Pathak Dec 05 '12 at 04:56
  • I wanted to post it because I looked for awhile to figure it out and wanted to save the next guy some time. – jpgunter Dec 05 '12 at 05:01
  • Okay. [You may provide the answer in the question and ask the question phrased as "is there a better answer".](http://meta.stackexchange.com/questions/17845/etiquette-for-answering-your-own-question) – Chankey Pathak Dec 05 '12 at 05:16
  • @Chankey Pathak: the overall thrust of that q/a seems to be very positive to just answering the question. Indeed, if this question had taken the approach you advocate, I would have been tempted to close it as "not a real question" - a better answer seems unlikely. – ysth Dec 05 '12 at 07:04
  • The last few lines are a perfect situation for a hash slice: `return @{ $$d_json{results}[0]{geometry}{location} }{qw/lat long/};`, intermediate arrows can be discarded. – amon Dec 05 '12 at 09:16
  • @amon I think mine is a little more readable, however I think this. – jpgunter Dec 05 '12 at 16:39
2

You can use Geo::Coder::Many to compare different services to find the one that thinks it's the most accurate. I've had good luck with it (US) in a mix of rural and urban addresses.

use Geo::Coder::Bing;
use Geo::Coder::Googlev3;
use Geo::Coder::Mapquest;
use Geo::Coder::OSM;
use Geo::Coder::Many;
use Geo::Coder::Many::Util qw( country_filter );

### Geo::Coder::Many object
my $geocoder_many = Geo::Coder::Many->new( );

$geocoder_many->add_geocoder({ geocoder => Geo::Coder::Googlev3->new });
$geocoder_many->add_geocoder({ geocoder => Geo::Coder::Bing->new( key => 'GET ONE' )});
$geocoder_many->add_geocoder({ geocoder => Geo::Coder::Mapquest->new( apikey => 'GET ONE' )});
$geocoder_many->add_geocoder({ geocoder => Geo::Coder::OSM->new( sources => 'mapquest' )});

$geocoder_many->set_filter_callback(country_filter('United States'));
$geocoder_many->set_picker_callback('max_precision');

for my $location (@locations) {
  my $result = $geocoder_many->geocode({ location => $location });
}
Oesor
  • 6,632
  • 2
  • 29
  • 56
1

There is a wrapper module for Google Geocoding API, Geo::Coder::Google:

#!/usr/bin/env perl
use strict;
use utf8;
use warnings qw(all);

use Data::Printer;
use Geo::Coder::Google;

my $geocoder = Geo::Coder::Google->new(apiver => 3);
my $location = $geocoder->geocode(location => 'Hollywood and Highland, Los Angeles, CA');

p $location->{geometry}{location};

This code prints:

\ {
    lat   34.101545,
    lng   -118.3386871
}

It is generally better to use an off-the-shelf CPAN module as it is backed by CPAN Testers service, so, if the API ever breaks, it would be easy to spot and report.

creaktive
  • 5,193
  • 2
  • 18
  • 32