Sunday, November 1, 2009

Address Validation with Google Maps

We've recently begun validating user-submitted addresses via Google Maps. As it turns out, this is very easy to do. All that's necessary is an HTTP call to this URL:

http://maps.google.com/maps/geo

We are using Django and Python. Below is a simple function to handle the geocoding. We have additional code to call this via AJAX via jQuery, as well as internal code to enforce our validation requirements.

The code not seen in this function comes from the Django settings file, and it only contains the arguments required by Google. Documentation for that is on Google's page describing use.

Here are the arguments we send (aside from, obviously, the address itself, which is urlencoded and sent as argument 'q'):

key: our Google Maps key
sensor: false
output: json
oe: utf8

Output:

Google Geocoding responds with a lot of useful information. The address object is 'Placemark.' For ambiguous addresses, it may return multiple placemarks. For our purposes, this counts as an invalid address. It also returns an accuracy number, from zero through nine. This is helpful in determining whether your user entered an address specific enough for your purposes. In our case, we can accept four, a fairly low score, since we are just estimating driving distance. But if you're planning to send something by mail, a higher score (at least eight) is required.

If there's interest, I may provide some JavaScript code, or maybe even a fully-functional example page in a later post. Our primary application requires a login to use, and is not available to the public.

def get_address_info(**kwargs):

#expects to receive address fields, bumps
#them up against Google, and returns the
#validation status

geocode_options = settings.GEOCODE_OPTIONS

address_string = ' '.join([
kwargs['street_line1'],
kwargs['street_line2'],
kwargs['city'],
kwargs['state'],
kwargs['postal_code'],
kwargs['country']]
).encode('utf-8')

geocode_options['q'] = address_string

try:
output = urlopen("%s?%s" % (settings.GEOCODE_URL, urlencode(geocode_options)))
except Exception, ex:
return False

geocode = simplejson.loads(output.read())

result = {
'latitude': '',
'longitude': '',
'accuracy': 0,
'address': '',
'multiple': False,
}

#if Google returned something juicy
if 'Placemark' in geocode:
if len(geocode['Placemark']) > 1:
result['multiple'] = True

result['accuracy'] = geocode['Placemark'][0]['AddressDetails']['Accuracy']

try:
result['address'] = geocode['Placemark'][0]['address']
except Exception, ex:
log.debug("Exception adding address to result dict: %s" % (ex,))

if (len(geocode['Placemark']) == 1 and result['accuracy'] >= 8):
result['latitude'] = geocode['Placemark'][0]['Point']['coordinates'][0]
result['longitude'] = geocode['Placemark'][0]['Point']['coordinates'][1]

return result


No comments:

Post a Comment