Skip to content

Commit

Permalink
Rewrite the wrapper using new Yahoo PlaceFinder API removing the outd…
Browse files Browse the repository at this point in the history
…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.
124 changes: 89 additions & 35 deletions geopy/geocoders/yahoo.py
@@ -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)

0 comments on commit 9dbfc49

Please sign in to comment.