gvsig-scripting / org.gvsig.scripting / trunk / org.gvsig.scripting / org.gvsig.scripting.app / org.gvsig.scripting.app.mainplugin / src / main / resources-plugin / scripting / lib / geopy / geocoders / yandex.py @ 545
History | View | Annotate | Download (5.2 KB)
1 |
"""
|
---|---|
2 |
:class:`Yandex` geocoder.
|
3 |
"""
|
4 |
|
5 |
from geopy.compat import urlencode |
6 |
|
7 |
from geopy.geocoders.base import Geocoder, DEFAULT_TIMEOUT |
8 |
from geopy.location import Location |
9 |
from geopy.exc import ( |
10 |
GeocoderServiceError, |
11 |
GeocoderParseError |
12 |
) |
13 |
from geopy.util import logger |
14 |
|
15 |
|
16 |
__all__ = ("Yandex", )
|
17 |
|
18 |
|
19 |
class Yandex(Geocoder): # pylint: disable=W0223 |
20 |
"""
|
21 |
Yandex geocoder, documentation at:
|
22 |
http://api.yandex.com/maps/doc/geocoder/desc/concepts/input_params.xml
|
23 |
"""
|
24 |
|
25 |
def __init__( |
26 |
self,
|
27 |
api_key=None,
|
28 |
lang=None,
|
29 |
timeout=DEFAULT_TIMEOUT, |
30 |
proxies=None
|
31 |
): |
32 |
"""
|
33 |
Create a Yandex-based geocoder.
|
34 |
|
35 |
.. versionadded:: 1.5.0
|
36 |
|
37 |
:param string api_key: Yandex API key (not obligatory)
|
38 |
http://api.yandex.ru/maps/form.xml
|
39 |
|
40 |
:param string lang: response locale, the following locales are
|
41 |
supported: "ru_RU" (default), "uk_UA", "be_BY", "en_US", "tr_TR"
|
42 |
|
43 |
:param int timeout: Time, in seconds, to wait for the geocoding service
|
44 |
to respond before raising a :class:`geopy.exc.GeocoderTimedOut`
|
45 |
exception.
|
46 |
|
47 |
:param dict proxies: If specified, routes this geocoder's requests
|
48 |
through the specified proxy. E.g., {"https": "192.0.2.0"}. For
|
49 |
more information, see documentation on
|
50 |
:class:`urllib2.ProxyHandler`.
|
51 |
"""
|
52 |
super(Yandex, self).__init__( |
53 |
scheme='http', timeout=timeout, proxies=proxies
|
54 |
) |
55 |
self.api_key = api_key
|
56 |
self.lang = lang
|
57 |
self.api = 'http://geocode-maps.yandex.ru/1.x/' |
58 |
|
59 |
def geocode(self, query, exactly_one=True, timeout=None): # pylint: disable=W0221 |
60 |
"""
|
61 |
Geocode a location query.
|
62 |
|
63 |
:param string query: The address or query you wish to geocode.
|
64 |
|
65 |
:param bool exactly_one: Return one result or a list of results, if
|
66 |
available.
|
67 |
|
68 |
:param int timeout: Time, in seconds, to wait for the geocoding service
|
69 |
to respond before raising a :class:`geopy.exc.GeocoderTimedOut`
|
70 |
exception. Set this only if you wish to override, on this call
|
71 |
only, the value set during the geocoder's initialization.
|
72 |
"""
|
73 |
params = { |
74 |
'geocode': query,
|
75 |
'format': 'json' |
76 |
} |
77 |
if not self.api_key is None: |
78 |
params['key'] = self.api_key |
79 |
if not self.lang is None: |
80 |
params['lang'] = self.lang |
81 |
if exactly_one is True: |
82 |
params['results'] = 1 |
83 |
url = "?".join((self.api, urlencode(params))) |
84 |
logger.debug("%s.geocode: %s", self.__class__.__name__, url) |
85 |
return self._parse_json( |
86 |
self._call_geocoder(url, timeout=timeout),
|
87 |
exactly_one, |
88 |
) |
89 |
|
90 |
def reverse( |
91 |
self,
|
92 |
query, |
93 |
exactly_one=False,
|
94 |
timeout=None,
|
95 |
): |
96 |
"""
|
97 |
Given a point, find an address.
|
98 |
|
99 |
:param string query: The coordinates for which you wish to obtain the
|
100 |
closest human-readable addresses.
|
101 |
:type query: :class:`geopy.point.Point`, list or tuple of (latitude,
|
102 |
longitude), or string as "%(latitude)s, %(longitude)s"
|
103 |
|
104 |
:param boolean exactly_one: Return one result or a list of results, if
|
105 |
available.
|
106 |
|
107 |
:param int timeout: Time, in seconds, to wait for the geocoding service
|
108 |
to respond before raising a :class:`geopy.exc.GeocoderTimedOut`
|
109 |
exception.
|
110 |
|
111 |
"""
|
112 |
try:
|
113 |
lat, lng = [ |
114 |
x.strip() for x in |
115 |
self._coerce_point_to_string(query).split(',') |
116 |
] |
117 |
except ValueError: |
118 |
raise ValueError("Must be a coordinate pair or Point") |
119 |
params = { |
120 |
'geocode': '{0},{1}'.format(lng, lat), |
121 |
'format': 'json' |
122 |
} |
123 |
if self.api_key is not None: |
124 |
params['key'] = self.api_key |
125 |
if self.lang is not None: |
126 |
params['lang'] = self.lang |
127 |
url = "?".join((self.api, urlencode(params))) |
128 |
logger.debug("%s.reverse: %s", self.__class__.__name__, url) |
129 |
return self._parse_json( |
130 |
self._call_geocoder(url, timeout=timeout),
|
131 |
exactly_one |
132 |
) |
133 |
|
134 |
def _parse_json(self, doc, exactly_one): |
135 |
"""
|
136 |
Parse JSON response body.
|
137 |
"""
|
138 |
if doc.get('error'): |
139 |
raise GeocoderServiceError(doc['error']['message']) |
140 |
|
141 |
try:
|
142 |
places = doc['response']['GeoObjectCollection']['featureMember'] |
143 |
except KeyError: |
144 |
raise GeocoderParseError('Failed to parse server response') |
145 |
|
146 |
def parse_code(place): |
147 |
"""
|
148 |
Parse each record.
|
149 |
"""
|
150 |
try:
|
151 |
place = place['GeoObject']
|
152 |
except KeyError: |
153 |
raise GeocoderParseError('Failed to parse server response') |
154 |
|
155 |
longitude, latitude = [ |
156 |
float(_) for _ in place['Point']['pos'].split(' ') |
157 |
] |
158 |
|
159 |
location = place.get('description')
|
160 |
|
161 |
return Location(location, (latitude, longitude), place)
|
162 |
|
163 |
if exactly_one:
|
164 |
return parse_code(places[0]) |
165 |
else:
|
166 |
return [parse_code(place) for place in places] |