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 / placefinder.py @ 545
History | View | Annotate | Download (6.08 KB)
1 |
"""
|
---|---|
2 |
:class:`.YahooPlaceFinder` geocoder.
|
3 |
"""
|
4 |
|
5 |
try:
|
6 |
from requests import get |
7 |
from requests_oauthlib import OAuth1 |
8 |
requests_missing = False
|
9 |
except ImportError: |
10 |
requests_missing = True
|
11 |
|
12 |
from geopy.geocoders.base import Geocoder, DEFAULT_TIMEOUT |
13 |
from geopy.exc import GeocoderParseError |
14 |
from geopy.location import Location |
15 |
from geopy.compat import string_compare, py3k |
16 |
|
17 |
|
18 |
__all__ = ("YahooPlaceFinder", )
|
19 |
|
20 |
|
21 |
class YahooPlaceFinder(Geocoder): # pylint: disable=W0223 |
22 |
"""
|
23 |
Geocoder that utilizes the Yahoo! BOSS PlaceFinder API. Documentation at:
|
24 |
https://developer.yahoo.com/boss/geo/docs/
|
25 |
"""
|
26 |
|
27 |
def __init__( |
28 |
self,
|
29 |
consumer_key, |
30 |
consumer_secret, |
31 |
timeout=DEFAULT_TIMEOUT, |
32 |
proxies=None
|
33 |
): # pylint: disable=R0913
|
34 |
"""
|
35 |
:param string consumer_key: Key provided by Yahoo.
|
36 |
|
37 |
:param string consumer_secret: Secret corresponding to the key
|
38 |
provided by Yahoo.
|
39 |
|
40 |
:param int timeout: Time, in seconds, to wait for the geocoding service
|
41 |
to respond before raising a :class:`geopy.exc.GeocoderTimedOut`
|
42 |
exception.
|
43 |
|
44 |
:param dict proxies: If specified, routes this geocoder"s requests
|
45 |
through the specified proxy. E.g., {"https": "192.0.2.0"}. For
|
46 |
more information, see documentation on
|
47 |
:class:`urllib2.ProxyHandler`.
|
48 |
|
49 |
.. versionadded:: 0.96
|
50 |
"""
|
51 |
if requests_missing:
|
52 |
raise ImportError( |
53 |
'requests-oauthlib is needed for YahooPlaceFinder.'
|
54 |
' Install with `pip install geopy -e ".[placefinder]"`.'
|
55 |
) |
56 |
super(YahooPlaceFinder, self).__init__( |
57 |
timeout=timeout, proxies=proxies |
58 |
) |
59 |
self.consumer_key = (
|
60 |
unicode(consumer_key)
|
61 |
if not py3k |
62 |
else str(consumer_key) |
63 |
) |
64 |
self.consumer_secret = (
|
65 |
unicode(consumer_secret)
|
66 |
if not py3k |
67 |
else str(consumer_secret) |
68 |
) |
69 |
self.auth = OAuth1(
|
70 |
client_key=self.consumer_key,
|
71 |
client_secret=self.consumer_secret,
|
72 |
signature_method="HMAC-SHA1",
|
73 |
signature_type="AUTH_HEADER",
|
74 |
) |
75 |
self.api = "https://yboss.yahooapis.com/geo/placefinder" |
76 |
|
77 |
@staticmethod
|
78 |
def _filtered_results(results, min_quality, valid_country_codes): |
79 |
"""
|
80 |
Returns only the results that meet the minimum quality threshold
|
81 |
and are located in expected countries.
|
82 |
"""
|
83 |
if min_quality:
|
84 |
results = [ |
85 |
loc |
86 |
for loc in results |
87 |
if int(loc.raw["quality"]) > min_quality |
88 |
] |
89 |
|
90 |
if valid_country_codes:
|
91 |
results = [ |
92 |
loc |
93 |
for loc in results |
94 |
if loc.raw["countrycode"] in valid_country_codes |
95 |
] |
96 |
|
97 |
return results
|
98 |
|
99 |
def _parse_response(self, content): |
100 |
"""
|
101 |
Returns the parsed result of a PlaceFinder API call.
|
102 |
"""
|
103 |
try:
|
104 |
placefinder = ( |
105 |
content["bossresponse"]["placefinder"] |
106 |
) |
107 |
if not len(placefinder) or not len(placefinder.get("results", [])): |
108 |
return None |
109 |
results = [ |
110 |
Location( |
111 |
self.humanize(place),
|
112 |
(float(place["latitude"]), float(place["longitude"])), |
113 |
raw=place |
114 |
) |
115 |
for place in placefinder["results"] |
116 |
] |
117 |
except (KeyError, ValueError): |
118 |
raise GeocoderParseError("Error parsing PlaceFinder result") |
119 |
|
120 |
return results
|
121 |
|
122 |
@staticmethod
|
123 |
def humanize(location): |
124 |
"""
|
125 |
Returns a human readable representation of a raw PlaceFinder location
|
126 |
"""
|
127 |
return ", ".join([ |
128 |
location[line] |
129 |
for line in ["line1", "line2", "line3", "line4"] |
130 |
if location[line]
|
131 |
]) |
132 |
|
133 |
def geocode( |
134 |
self,
|
135 |
query, |
136 |
exactly_one=True,
|
137 |
timeout=None,
|
138 |
min_quality=0,
|
139 |
reverse=False,
|
140 |
valid_country_codes=None,
|
141 |
): # pylint: disable=W0221,R0913
|
142 |
"""
|
143 |
Geocode a location query.
|
144 |
|
145 |
:param string query: The address or query you wish to geocode.
|
146 |
|
147 |
:param bool exactly_one: Return one result or a list of results, if
|
148 |
available.
|
149 |
|
150 |
:param int min_quality:
|
151 |
|
152 |
:param bool reverse:
|
153 |
|
154 |
:param valid_country_codes:
|
155 |
:type valid_country_codes: list or tuple
|
156 |
"""
|
157 |
params = { |
158 |
"location": query,
|
159 |
"flags": "J", # JSON |
160 |
} |
161 |
|
162 |
if reverse is True: |
163 |
params["gflags"] = "R" |
164 |
if exactly_one is True: |
165 |
params["count"] = "1" |
166 |
|
167 |
response = self._call_geocoder(
|
168 |
self.api,
|
169 |
timeout=timeout, |
170 |
requester=get, |
171 |
params=params, |
172 |
auth=self.auth,
|
173 |
) |
174 |
results = self._parse_response(response)
|
175 |
if results is None: |
176 |
return None |
177 |
|
178 |
results = self._filtered_results(
|
179 |
results, |
180 |
min_quality, |
181 |
valid_country_codes, |
182 |
) |
183 |
|
184 |
if exactly_one:
|
185 |
return results[0] |
186 |
else:
|
187 |
return results
|
188 |
|
189 |
def reverse(self, query, exactly_one=True, timeout=None): |
190 |
"""
|
191 |
Returns a reverse geocoded location using Yahoo"s PlaceFinder API.
|
192 |
|
193 |
:param query: The coordinates for which you wish to obtain the
|
194 |
closest human-readable addresses.
|
195 |
:type query: :class:`geopy.point.Point`, list or tuple of (latitude,
|
196 |
longitude), or string as "%(latitude)s, %(longitude)s"
|
197 |
|
198 |
:param bool exactly_one: Return one result or a list of results, if
|
199 |
available.
|
200 |
"""
|
201 |
query = self._coerce_point_to_string(query)
|
202 |
if isinstance(query, string_compare): |
203 |
query = query.replace(" ", "") # oauth signature failure; todo |
204 |
return self.geocode( |
205 |
query, |
206 |
exactly_one=exactly_one, |
207 |
timeout=timeout, |
208 |
reverse=True
|
209 |
) |