forked from geopy/geopy
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Rewrite the wrapper using new Yahoo PlaceFinder API removing the outd…
…ated one. Also include the revere geo lookup git-svn-id: https://geopy.googlecode.com/svn/trunk@151 535ce8a4-231d-0410-ac7f-15f3cd728b52
- Loading branch information
mike.tigas@gmail.com
committed
Jun 17, 2011
1 parent
56f2de2
commit 9dbfc49
Showing
1 changed file
with
89 additions
and
35 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,69 +1,123 @@ | ||
""" | ||
Wrapper to the Yahoo's new PlaceFinder API. (doc says that the API RELEASE 1.0 (22 JUNE 2010)) | ||
""" | ||
import xml.dom.minidom | ||
from geopy import util | ||
from geopy import Point | ||
from urllib import urlencode | ||
from urllib2 import urlopen | ||
from geopy.geocoders.base import Geocoder | ||
import simplejson | ||
|
||
|
||
class Yahoo(Geocoder): | ||
|
||
BASE_URL = "http://api.local.yahoo.com/MapsService/V1/geocode?%s" | ||
BASE_URL = "http://where.yahooapis.com/geocode?%s" | ||
|
||
def __init__(self, app_id, format_string='%s', output_format='xml'): | ||
self.app_id = app_id | ||
self.format_string = format_string | ||
self.output_format = output_format.lower() | ||
# output_format could be 'xml' or 'json', | ||
# Yahoo API supports serialized PHP too, but not yet supported in this library | ||
self.appid = app_id | ||
self.output_format = output_format | ||
|
||
def geocode(self, string, exactly_one=True): | ||
params = {'location': self.format_string % string, | ||
'output': self.output_format, | ||
'appid': self.app_id | ||
params = {'location': string, | ||
'appid': self.appid | ||
} | ||
if self.output_format == 'json': | ||
params['flags'] = 'J' | ||
url = self.BASE_URL % urlencode(params) | ||
return self.geocode_url(url, exactly_one) | ||
util.logger.debug("Fetching %s..." % url) | ||
try: | ||
return self.geocode_url(url, exactly_one) | ||
except httplib.BadStatusLine: | ||
util.logger.debug('ERR_EMPTY_RESPONSE: Server sent no data') | ||
raise | ||
|
||
def geocode_url(self, url, exactly_one=True): | ||
util.logger.debug("Fetching %s..." % url) | ||
page = urlopen(url) | ||
|
||
return self.parse_xml(page, exactly_one) | ||
|
||
parse = getattr(self, 'parse_' + self.output_format) | ||
return parse(page, exactly_one) | ||
def parse_xml(self, page, exactly_one=True): | ||
if not isinstance(page, basestring): | ||
page = util.decode_page(page) | ||
|
||
doc = xml.dom.minidom.parseString(page) | ||
results = doc.getElementsByTagName('Result') | ||
results = doc.getElementsByTagName('ResultSet')[0].getElementsByTagName('Result') | ||
|
||
#if exactly_one and len(results) != 1: | ||
# raise ValueError("Didn't find exactly one place! " \ | ||
# "(Found %d.)" % len(results)) | ||
|
||
if not results: | ||
raise ValueError("No results found") | ||
|
||
def parse_result(result): | ||
strip = ", \n" | ||
address = util.get_first_text(result, 'Address', strip) | ||
city = util.get_first_text(result, 'City', strip) | ||
state = util.get_first_text(result, 'State', strip) | ||
zip = util.get_first_text(result, 'Zip', strip) | ||
country = util.get_first_text(result, 'Country', strip) | ||
line1= util.get_first_text(result, 'line1', strip) | ||
line2 = util.get_first_text(result, 'line2', strip) | ||
line3 = util.get_first_text(result, 'line3', strip) | ||
line4 = util.get_first_text(result, 'line4', strip) | ||
address = util.join_filter(", ", [line1, line2, line3, line4]) | ||
city = util.get_first_text(result, 'city', strip) | ||
state = util.get_first_text(result, 'state', strip) | ||
zip = util.get_first_text(result, 'uzip', strip) | ||
country = util.get_first_text(result, 'country', strip) | ||
city_state = util.join_filter(", ", [city, state]) | ||
place = util.join_filter(" ", [city_state, zip]) | ||
location = util.join_filter(", ", [address, place, country]) | ||
latitude = float(util.get_first_text(result, 'Latitude')) or None | ||
longitude = float(util.get_first_text(result, 'Longitude')) or None | ||
|
||
# TODO use Point/Location object API in 0.95 | ||
#if latitude and longitude: | ||
# point = Point(latitude, longitude) | ||
#else: | ||
# point = Non | ||
#return Location(location, point, { | ||
# 'Address': address, | ||
# 'City': city, | ||
# 'State': state, | ||
# 'Zip': zip, | ||
# 'Country': country | ||
#}) | ||
|
||
return address, (latitude, longitude) | ||
latitude = util.get_first_text(result, 'latitude') or None | ||
longitude = util.get_first_text(result, 'longitude') or None | ||
if latitude and longitude: | ||
point = Point(latitude, longitude) | ||
else: | ||
point = None | ||
return (location, (latitude, longitude)) | ||
|
||
if exactly_one: | ||
return parse_result(results[0]) | ||
else: | ||
return [parse_result(result) for result in results] | ||
|
||
def parse_json(self, page, exactly_one=True): | ||
if not isinstance(page, basestring): | ||
page = util.decode_page(page) | ||
json = simplejson.loads(page) | ||
results = json.get('ResultSet', []).get('Results', []) | ||
|
||
#if (exactly_one and len(results) != 1) and (not reverse): | ||
# raise ValueError("Didn't find exactly one placemark! " \ | ||
# "(Found %d.)" % len(results)) | ||
if not results: | ||
raise ValueError("No results found") | ||
|
||
def parse_result(p): | ||
line1, line2, line3, line4 = p.get('line1'), p.get('line2'), p.get('line3'), p.get('line4') | ||
address = util.join_filter(", ", [line1, line2, line3, line4]) | ||
city = p.get('city') | ||
state = p.get('state') | ||
country = p.get('country') | ||
location = util.join_filter(", ", [address, city, country]) | ||
lat, lng = p.get('latitude'), p.get('longitude') | ||
if lat and lng: | ||
point = Point(lat, lng) | ||
else: | ||
point = None | ||
return (location, (lat, lng)) | ||
|
||
if exactly_one: | ||
return parse_result(results[0]) | ||
else: | ||
return [parse_result(result) for result in results] | ||
|
||
def reverse(self, coord, exactly_one=True): | ||
(lat, lng) = coord | ||
params = {'location': '%s,%s' % (lat, lng), | ||
'gflags' : 'R', | ||
'appid': self.appid | ||
} | ||
if self.output_format == 'json': | ||
params['flags'] = 'J' | ||
url = self.BASE_URL % urlencode(params) | ||
return self.geocode_url(url, exactly_one) |