File Coverage

blib/lib/Geo/Parser/Text.pm
Criterion Covered Total %
statement 35 75 46.6
branch 0 4 0.0
condition n/a
subroutine 12 16 75.0
pod 2 4 50.0
total 49 99 49.4


line stmt bran cond sub pod time code
1             package Geo::Parser::Text;
2              
3 1     1   52212 use 5.006;
  1         3  
4 1     1   4 use strict;
  1         2  
  1         17  
5 1     1   3 use warnings;
  1         2  
  1         32  
6 1     1   455 use utf8::all;
  1         40454  
  1         5  
7 1     1   1236 use open ':utf8';
  1         2  
  1         3  
8              
9 1     1   693 use XML::Simple;
  1         6721  
  1         5  
10 1     1   595 use LWP::UserAgent;
  1         37218  
  1         35  
11 1     1   7 use HTTP::Request;
  1         2  
  1         23  
12 1     1   4 use URI;
  1         7  
  1         18  
13 1     1   519 use Data::Dumper;
  1         4835  
  1         50  
14              
15              
16 1     1   6 use constant DEBUG => 0;
  1         2  
  1         44  
17 1     1   6 use constant GEO_HOST => q{https://geocode.xyz};
  1         1  
  1         577  
18              
19             sub new {
20 0     0 1   my $class = shift;
21 0           my $self = {
22             geo_host => shift
23             };
24              
25 0           bless ($self, $class);
26 0           return $self;
27             }
28              
29             sub geodata {
30 0     0 0   my $self = shift;
31 0 0         $self->{geodata} = $_[0] if $_[0];
32 0           return $self->{geodata};
33             }
34              
35             sub geocode {
36 0     0 1   my $self = shift;
37 0           my %params = @_;
38              
39 0           my %form_values;
40 0           foreach my $param (keys %params) {
41 0           $form_values{$param} = $params{$param};
42             }
43 0           $form_values{geoit} = 'XML'; #default
44              
45 0           warn Data::Dumper->Dump([\%form_values],['Form Values']) if DEBUG;
46              
47 0           $self->process_request(%form_values);
48              
49 0           my $geodata = $self->geodata;
50 0           my @a = split(//,$geodata);
51 0           my $geod = pop @a;
52 0           $geod = '' . $geod;
53 0           my %t;
54 0           my $ref = \%t;
55              
56 0           eval {
57 0           $ref = XMLin($geod);
58             };
59 0           warn Data::Dumper->Dump([$ref],['Response']) if DEBUG;
60              
61 0           $self->geodata($ref);
62              
63 0           return $self->geodata;
64              
65             }
66              
67             sub process_request {
68 0     0 0   my $self = shift;
69 0           my %form_values = @_;
70 0 0         $self->{geo_host} = GEO_HOST unless $self->{geo_host};
71              
72 0           my $uri = URI->new;
73 0           $uri->query_form(%form_values);
74 0           my $ua = LWP::UserAgent->new;
75 0           my $req = HTTP::Request->new(POST => $self->{geo_host});
76 0           $req->content_type('application/x-www-form-urlencoded');
77 0           $req->content($uri->query);
78              
79 0           my $res = $ua->request($req);
80 0           my $result = $res->as_string;
81              
82 0           warn $result if DEBUG;
83              
84 0           my $geodata = $result;
85              
86              
87 0           return $self->geodata($geodata);
88             }
89              
90              
91              
92             =head1 NAME
93              
94             Geo::Parser::Text - Perl extension for geoparsing, geocoding and standardizing locations from free form text. Worldwide Coverage. Geocode places to latitude, longitude, elevation.
95             And vice-versa.
96              
97             =head1 VERSION
98              
99             Version 0.051
100              
101             =cut
102              
103             our $VERSION = '0.051';
104              
105              
106             =head1 SYNOPSIS
107              
108             use Geo::Parser::Text;
109            
110             # initialize with your host
111             my $g = Geo::Parser::Text->new([geo_host]);
112              
113             # Scan text in $str for locations...
114             my $hashref = $g->geocode(scantext=>$str);
115              
116             # Geocode a single location from $str...
117             my $hashref = $g->geocode(locate=>$str);
118             #
119            
120             # Example...
121              
122             #!/usr/bin/perl
123             use strict;
124             use Geo::Parser::Text;
125             use Data::Dumper;
126             my $g = Geo::Parser::Text->new('https://geocode.xyz');
127             my $str = "The most important museums of Amsterdam are located on the Museumplein, located at the southwestern side of the Rijksmuseum.";
128             my $ref = $g->geocode(scantext=>$str,region=>'NL');
129             print Dumper $ref;
130              
131             #expected response
132             $Response = {
133             'match' => [
134             {
135             'longt' => '4.88355',
136             'location' => 'RIJKSMUSEUM, AMSTERDAM, NL',
137             'matchtype' => 'street',
138             'confidence' => '1.0',
139             'MentionIndices' => '112',
140             'latt' => '52.35976'
141             },
142             {
143             'longt' => '4.87986',
144             'location' => 'MUSEUMPLEIN, AMSTERDAM, NL',
145             'matchtype' => 'street',
146             'confidence' => '1.0',
147             'MentionIndices' => '59',
148             'latt' => '52.35791'
149             },
150             {
151             'longt' => '4.89574',
152             'location' => 'Amsterdam,NL',
153             'matchtype' => 'locality',
154             'confidence' => '0.4',
155             'MentionIndices' => '30',
156             'latt' => '52.36014'
157             }
158             ]
159             };
160            
161              
162             #or
163              
164             #forward geocode and cleanup/standardize input address
165              
166             my $ref = $g->geocode(locate=>'10 Downing St, Londino UK');
167             print Dumper $ref;
168              
169             #expected response
170             $Response = {
171             'standard' => {
172             'stnumber' => '10',
173             'addresst' => 'DOWNING STREET',
174             'city' => 'Londino',
175             'prov' => 'UK',
176             'countryname' => 'United Kingdom',
177             'postal' => {},
178             'confidence' => '0.60'
179             },
180             'longt' => '-0.12768',
181             'elevation' => {},
182             'latt' => '51.50354'
183             };
184              
185              
186              
187             #reverse geocode
188             my $ref = $g->geocode(locate=>'51.5034066,-0.1275923');
189             print Dumper $ref;
190              
191             #expected response
192             $Response = {
193             'confidence' => '0.9',
194             'distance' => '0',
195             'city' => 'London',
196             'inlatt' => '51.50341',
197             'stnumber' => '9',
198             'latt' => '51.50328',
199             'postal' => 'SW1A 2AG',
200             'staddress' => 'Downing Street',
201             'longt' => '-0.12751',
202             'inlongt' => '-0.12759',
203             'prov' => 'UK'
204             };
205              
206            
207             =head1 DESCRIPTION
208              
209             This module provides a Perl front end for the geocode.xyz, geocoder.ca API.
210              
211             It allows the programmer to extract locations containing street addresses, street intersections and city names along with their geocoded latitude,longitude from bodies of text such as microblogs or wikipedia entries. (It should work with any type of text, but dumping html text or paragraphs containing over 200 words, will slow down the response.
212              
213             If you need faster parsing grab the geocode.xyz server image on the AWS, and run it on a faster server.
214              
215             If you run your own instance, make sure to pass the instance ip address or domain name at invocation eg, Geo::Parser::Text->new($server). For North American locations use geocoder.ca
216              
217             The api also geocodes single locations (returning the location matched with the highest probability from a string of text. If you pass a latitude,longitude pair, it will reverse geocode that point)
218              
219             Geocoding requests also return the elevation value of the point in meters.
220              
221             For explanation on the API responses see https://geocode.xyz/api
222            
223             =head2 METHODS
224              
225             =head2 new
226              
227             my $geo = new ( host => 'https://geocode.xyz');
228              
229             Initialize with the default server. https://geocode.xyz for Worldwide coverage, https://geocoder.ca for North America.
230              
231             =head2 geocode
232              
233             my $ref = $geo->geocode(locate=>'Paris France');
234             or
235             my $ref = $geo->geocode(scantext=>'Paris France');
236              
237             Set the text to be scanned or string to be geocoded and return a hash reference with the response.
238            
239             Takes a hash of parameter names and values.
240             You are required to pass a hash to geocode with either the scantext or locate key set to the text you want to geocode/geoparse.
241              
242             You may also pass other optional arguments as described in the API at https://geocode.xyz/api.
243              
244             Foe eg:
245             my $ref = $geo->geocode(locate=>'Paris France', auth=>'your auth code for unthrottled access', region=>'FR');
246              
247              
248              
249             =over 1
250              
251             =back
252             =head1 EXPORT
253              
254             None by default.
255              
256              
257             =head1 REQUIREMENTS
258              
259             XML::Simple,
260             LWP::UserAgent,
261             HTTP::Request,
262             URI
263             Data::Dumper
264              
265             =head1 SEE ALSO
266              
267             This module was featured in the 2016 Perl Advent Calendar. L.
268              
269             =head1 AUTHOR
270              
271             Ervin Ruci, C<< >>
272              
273             =head1 BUGS
274              
275             Please report any bugs or feature requests to C, or through
276             the web interface at L. I will be notified, and then you'll
277             automatically be notified of progress on your bug as I make changes.
278              
279              
280              
281              
282             =head1 SUPPORT
283              
284             You can find documentation for this module with the perldoc command.
285              
286             perldoc Geo::Parser::Text
287              
288              
289             You can also look for information at:
290              
291             =over 4
292              
293             =item * RT: CPAN's request tracker (report bugs here)
294              
295             L
296              
297             =item * AnnoCPAN: Annotated CPAN documentation
298              
299             L
300              
301             =item * CPAN Ratings
302              
303             L
304              
305             =item * Search CPAN
306              
307             L
308              
309             =back
310              
311              
312             =head1 ACKNOWLEDGEMENTS
313              
314              
315             =head1 LICENSE AND COPYRIGHT
316              
317             Copyright 2018 Ervin Ruci.
318              
319             This program is free software; you can redistribute it and/or modify it
320             under the terms of the the Artistic License (2.0). You may obtain a
321             copy of the full license at:
322              
323             L
324              
325             Any use, modification, and distribution of the Standard or Modified
326             Versions is governed by this Artistic License. By using, modifying or
327             distributing the Package, you accept this license. Do not use, modify,
328             or distribute the Package, if you do not accept this license.
329              
330             If your Modified Version has been derived from a Modified Version made
331             by someone other than you, you are nevertheless required to ensure that
332             your Modified Version complies with the requirements of this license.
333              
334             This license does not grant you the right to use any trademark, service
335             mark, tradename, or logo of the Copyright Holder.
336              
337             This license includes the non-exclusive, worldwide, free-of-charge
338             patent license to make, have made, use, offer to sell, sell, import and
339             otherwise transfer the Package with respect to any patent claims
340             licensable by the Copyright Holder that are necessarily infringed by the
341             Package. If you institute patent litigation (including a cross-claim or
342             counterclaim) against any party alleging that the Package constitutes
343             direct or contributory patent infringement, then this Artistic License
344             to you shall terminate on the date that such litigation is filed.
345              
346             Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER
347             AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
348             THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
349             PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY
350             YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR
351             CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR
352             CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE,
353             EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
354              
355              
356             =head1 SEE ALSO
357              
358             Geo::Coder::CA
359             Geo::Coder::List
360             HTML::GoogleMaps::V3
361             Geo::Coder::OpenCage
362             Geo::Parse::OSM
363             Text::NLP
364             =cut
365              
366             1; # End of Geo::Parser::Text