I have used this code below in the past. It works pretty well.
#http://stackoverflow.com/questions/14580540/get-location-coordinates-using-bing-or-google-api-in-python
import urllib
import json
import arcpy
import time
import os
arcpy.env.overwriteOutput = True
GOOGLE = 'http://maps.googleapis.com/maps/api/geocode/json?'
def Message(msg):
print str(msg)
arcpy.AddMessage(str(msg))
def googleGeocoder(new_fc, addresses=[]):
"""
Quick and dirty geocode.
Required:
new_fc -- new point feature class for geocoded addresses
addresses -- dictionary of address and feature name {'address' : 'feature description',..}
or a list of addresses ['address, city, state, zip'...]
Addresses can be in one of the below formats.
# example: pass addresses with description as dictionary
addresses = {"400 N 1st Ave W, Hartley, IA, 51346" : "Prins Laundromat",
"120 S 8th Ave W, Hartley, IA, 51346" : "Hengeveld Construction",
"173 S Central Ave, Hartley, IA, 51346" : "Legal Eyes"}
# example: pass addresses in as a list
addresses = ["901 N Broadway, Saint Louis, Missouri, 63102",
"10701 Lambert International Blvd, Saint Louis",
"15193 Olive Blvd, Chesterfield, Missouri, 63"]
"""
# check to see if addresses are provided as dict
hasFeature = True
if isinstance(addresses, basestring):
addresses = [addresses]
if not isinstance(addresses, dict):
addresses = dict((a, '') for a in addresses)
hasFeature = False
# version info
# sets projection to WGS 1984 GCS
prj = arcpy.SpatialReference(4326)
# dictionary to store addresses and points
addr = {}
bad = []
for address, name in addresses.iteritems():
try:
pt = google_getCoordinates(address)
addr[(address, name)] = arcpy.PointGeometry(arcpy.Point(*pt), prj)
except:
Message("Could not geocode address \"{0}\"".format(address))
bad.append(address)
# create new feature class
f_length = max(len(a) for a in addresses) + 5
if f_length > 255:
f_length = 255
if arcpy.Exists(new_fc):
arcpy.Delete_management(new_fc)
arcpy.CreateFeatureclass_management(os.path.dirname(new_fc),
os.path.basename(new_fc),
'POINT', spatial_reference=prj)
arcpy.AddField_management(new_fc, 'Address', 'TEXT', field_length=f_length)
arcpy.AddField_management(new_fc, 'Feature', 'TEXT', field_length=100)
arcpy.management.AddField(new_fc, 'X_COORD', 'DOUBLE')
arcpy.management.AddField(new_fc, 'Y_COORD', 'DOUBLE')
# Insert rows
fields = ['SHAPE@', 'Address', 'Feature', 'X_COORD', 'Y_COORD']
with arcpy.da.InsertCursor(new_fc, fields) as irows:
for attributes, pt in addr.iteritems():
point = pt.centroid
irows.insertRow((pt,) + attributes + (point.X, point.Y))
Message('Geocoded address: {0}'.format(attributes[0]))
del irows
# Delete feature field if no feature names supplied
if not hasFeature:
arcpy.DeleteField_management(new_fc, ['Feature'])
# if bad records
if bad:
date = time.strftime('_%m_%d_%Y')
txt = r'C:\Users\{0}\Desktop\Geocode_fail_{1}.txt'.format(os.environ['USERNAME'], date)
with open(txt, 'w') as f:
f.writelines('\n'.join(bad))
os.startfile(txt)
return new_fc
def google_getCoordinates(query, from_sensor=False, googleGeocodeUrl=GOOGLE):
"""use google geocoder to get coordinates from adddress
query -- address to geocode
"""
query = query.encode('utf-8')
params = {
'address': query,
'sensor': "true" if from_sensor else "false"
}
url = googleGeocodeUrl + urllib.urlencode(params)
json_response = urllib.urlopen(url)
response = json.loads(json_response.read())
if response['results']:
location = response['results'][0]['geometry']['location']
latitude, longitude = location['lat'], location['lng']
else:
latitude, longitude = None, None
print query, "<no results>"
return (longitude, latitude) # as x,y tuple
if __name__ == '__main__':
# example 1: pass addresses in with description as dictionary
addresses = {"400 N 1st Ave W, Hartley, IA, 51346" : "Prins Laundromat",
"120 S 8th Ave W, Hartley, IA, 51346" : "Hengeveld Construction",
"173 S Central Ave, Hartley, IA, 51346" : "Legal Eyes"}
test = os.path.join(os.environ['USERPROFILE'], r'Desktop\test_gc.shp')
googleGeocoder(test, addresses)
# example 2: pass addresses in as a simple list
addresses = ["901 N Broadway, Saint Louis, Missouri, 63102",
"10701 Lambert International Blvd, Saint Louis",
"15193 Olive Blvd, Chesterfield, Missouri, 63"]
test = os.path.join(os.environ['USERPROFILE'], r'Desktop\test_gc_list.shp')
googleGeocoder(test, addresses)