In Perl how do get the lat and long from an arbitrary address? It is OK to use an external API.
Asked
Active
Viewed 6,655 times
3
-
Is there any way of getting an "over limit status" message from the library? – new_linux_user Jan 20 '18 at 00:05
3 Answers
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
-
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
-
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
-
Very nice, and as @Oesor pointed out, you can use Geo::Coder::Many to compare the results from a few APIs. – jpgunter Dec 05 '12 at 16:37
-
Is there any way of getting an "over limit status" message from thelibrary? – new_linux_user Jan 20 '18 at 00:05