Geo::Yandex - Performs geographical queries using Yandex Maps API


Geo-Yandex documentation Contained in the Geo-Yandex distribution.

Index


Code Index:

NAME

Top

Geo::Yandex - Performs geographical queries using Yandex Maps API

SYNOPSIS

Top

    use Geo::Yandex;

    # Address to search
    my $addr = 'Москва, Красная площадь, 1';

    # Personal API key, should be obtained at http://api.yandex.ru/maps/form.xml
    my $key = '. . .';

    # New geo object, note to use the key
    my $geo = new Geo::Yandex($key);

    # Search locations with a given address
    my @locations = $geo->location(address => $addr);

    # Or specify query in more details
    my @locations = $geo->location(
        address => $addr,
        results => 3,
        skip    => 2,
        center  => '37.618920,55.756994',
        size    => '0.552069,0.400552'
    );    

    # Locations are an array of Geo::Yandex::Location elements
    for my $item (@locations) {
        say $item->address . ' (' . $item->kind .') ' .
            $item->latitude . ',' . $item->longitude;
    }

    


ABSTRACT

Top

Geo::Yandex is a Perl interface for the part of Yandex Maps API which retrieves geographical data for text query.

DESCRIPTION

Top

Yandex Maps API is a set of tools for working with http://maps.yandex.ru website both with JavaScript queries and HTTP negotiations. Full description of the interface can be found at http://api.yandex.ru/maps/doc/ (in Russian).

All the work is done by an instance of Geo::Yandex class.

new

Creates a new Geo::Yandex object. The only argument, which is required, is a personal key that should be issued by Yandex before using API. To obtain the key you need to fill the form at http://api.yandex.ru/maps/form.xml.

    my $geo = new Geo::Yandex($key);

location

Launches search query to Yandex and returns the list of locations which match to the given address (passed in address parameter).

    my @locations = $geo->location(address => $addr);

The list returned by this method is combined of elements of the type Geo::Yandex::Location. If no results were found, return is an empty list.

parameters of location method

address

This is the only parameter which is requered for performing the search. It is a text string containing the address of the location being searched. May be in less or more free form.

results

Optional parameter which sets the limit of search. No more results will appear than a number set by this parameter.

skip

Optional parameter to skip several first results. Useful in pair with results parameter for organizing paginated output.

center, size

    my @locations = $geo->location(
        address => $addr,
        center  => '37.618920,55.756994',
        size    => '0.552069,0.400552'
    );    

These two parameters restrict the search area with a boundary located withing (longitude, latitude) pair set in center. This point will be located in the center of search area. To set width and height of the search block use size parameter. Both parameters are optional. Each should contain a pair of numbers (geographical measure - degree) separated by a comma.

Please note that you should not expect that center and size parameters will bring rigid boundaries of the area; those are just hints for the search engine. Seems to be weird stuff.

AUTHOR

Top

Andrew Shitov, <andy@shitov.ru>

COPYRIGHT AND LICENCE

Top


Geo-Yandex documentation Contained in the Geo-Yandex distribution.

package Geo::Yandex;

use vars qw ($VERSION);
$VERSION = '0.3';

my $API = 'geocode-maps.yandex.ru/1.x';

use strict;
use utf8;
use Geo::Yandex::Location;
use LWP::UserAgent;
use URI::Escape;
use XML::LibXML;

sub new {
    my ($class, $key) = @_;
    
    unless ($key) {
        warn "API key is not specified\n";
        return undef;
    }

    my $this = {
        key => $key,
        error => '',
    };
    
    bless $this, $class;
    
    return $this;
}

sub location {
    my ($this, %data) = @_;

    $this->{'error'} = '';

    unless ($data{'address'} && $this->{'key'}) {
        $this->{'error'} = "Either address or API key are not specified\n";
        return undef;
    }
    
    my $uri
        = "http://$API/?key=" . uri_escape_utf8($this->{'key'})
        . '&geocode=' . uri_escape_utf8($data{'address'});
        
    $uri .= '&ll='      . $data{'center'}   if $data{'center'};
    $uri .= '&spn='     . $data{'size'}     if $data{'size'};
    $uri .= '&results=' . $data{'results'}  if $data{'results'};
    $uri .= '&skip='    . $data{'skip'}     if $data{'skip'};

    my $useragent = new LWP::UserAgent;
    my $request = new HTTP::Request(GET => $uri);
    my $response = $useragent->request($request);

    if ($response->is_success) {
        return $this->parse_response($response->content);        
    }
    else {
        $this->{'error'} = "HTTP request error: " . $response->status_line . "\n";
        return ();
    }    
}

sub parse_response {
    my ($this, $content) = @_;

    my $parser = new XML::LibXML;
    my $xml = $parser->parse_string($content);
    
    my $context = new XML::LibXML::XPathContext;
    $context->registerNs('ymaps', 'http://maps.yandex.ru/ymaps/1.x');
    $context->registerNs('gml', 'http://www.opengis.net/gml');
    $context->registerNs('xal', 'urn:oasis:names:tc:ciq:xsdschema:xAL:2.0');
    $context->registerNs('ygeo', 'http://maps.yandex.ru/geocoder/1.x');
    
    my $ymaps = ${$context->findnodes('/ymaps:ymaps', $xml)}[0];
    my $request = ${$context->findnodes('.//ygeo:request', $ymaps)}[0]->textContent;
    my $found = ${$context->findnodes('.//ygeo:found', $ymaps)}[0]->textContent;

    return () unless $found;

    my @featureMembers = $context->findnodes('.//gml:featureMember', $ymaps);
    my @ret;
    foreach my $featureMember (@featureMembers) {
        push @ret, new Geo::Yandex::Location($context, $featureMember);
    }
    
    return @ret;
}

1;

__END__