Permalink
Browse files

Rewrite the wrapper using new Yahoo PlaceFinder API removing the outd…

…ated one.

Also include the revere geo lookup
  • Loading branch information...
1 parent 56f2de2 commit 6c8b34b3050df494b4c8e30753337bf085a6ad3b Devi committed Jun 17, 2011
Showing with 89 additions and 35 deletions.
  1. +89 −35 geopy/geocoders/yahoo.py
View
124 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 6c8b34b

Please sign in to comment.