2

I have a table of addresses, and I need my Python script to use my Google API geolocate function to return lat/long coordinates for each and add to a new field in the same row for each address. The geocode function works fine- I just can't get the script to iterate through each row of the table, add the address to the function, and then copy the output lat/long to the field in the same row. here's what I have:

import urllib, json, time, arcpy

arcpy.env.workspace = "D:/GIS/addr.dbf"

#sets variables, adds new field to hold lat/long coordinates
fc = 'addr.dbf'
field1 = 'address'
field2 = 'loc'
arcpy.AddField_management(fc, field2, "TEXT")


#function that uses Google API to geolocate- this part works consistently
def geolocate(address, 
api="key_here",delay=4):
  base = r"https://maps.googleapis.com/maps/api/geocode/json?"
  addP = "address=" + address.replace(" ","+")
  gUrl = base + addP + "&key=" + api
  response = urllib.urlopen(gUrl)
  jres = response.read()
  jData = json.loads(jres)
  if jData['status'] == 'OK':
    resu = jData['results'][0]
    finList = [resu['formatted_address'],resu['geometry']['location'] 
    ['lat'],resu['geometry']['location']['lng']]
  else:
    finList = [None,None,None]
  time.sleep(delay)
  return finList


#adds address field as text to geolocate in function, adds output lat/long 
#(indexed locations 0 and 1 from the finList output)
##this is the part that doesn't work!
geo = geolocate(address = field1)
cursor = arcpy.UpdateCursor(fc, [field1, field2])
for row in cursor:
  field2 = geo[0], geo[1]
  cursor.updateRow(row);
0

2 Answers 2

1

first thing: download https://pypi.python.org/pypi/geocoder/1.8.0 this geocoder with pip install geocoder from your cmd.

now to simplify your code

import arcpy, geocoder

#sets variables, adds new field to hold lat/long coordinates
fc = r'dataset'
field1 = 'Address'
field2 = 'loc'
arcpy.AddField_management(fc, field2, "TEXT")

#function that uses Geocoder goolge maps API with simplicity
def geolocate(address):
    try:
        g=geocoder.google(address)
        x=g.latlng[1]
        y=g.latlng[0]
        coords="{} {}".format(x,y)
    except:
        coords="couldnt geocode"
    return coords
#use the da cursor they are more efficient
with arcpy.da.UpdateCursor(fc,(field1,field2)) as cursor:
    for row in cursor:
        row[1]=geolocate(row[0])
        cursor.updateRow(row)

in your original code geo = geolocate(address = field1) this line needed to be in the for loop to geocode row by row.

you can add various print statements along the way but this should work for you.

*if you do not want to use the geocoder library then just use your geolocate function instead of mine.

UPDATE

based on your comment to return the lat long values in their respective fields, I used a simple class

import arcpy, geocoder

#sets variables, adds new field to hold lat/long coordinates
fc = r'dataset'
field1 = 'Address'
latitude = 'Latitude'
longitude='Longitude'
arcpy.AddField_management(fc, latitude, "TEXT")
arcpy.AddField_management(fc, longitude, "TEXT")

#class that uses Geocoder goolge maps API
class geolocate:
    def __init__(self,address):
        self.address=address
        self.x=''
        self.y=''
    def latlongs(self):
        try:
            g=geocoder.google(self.address)
            self.x=str(g.latlng[1])
            self.y=str(g.latlng[0])
        except:
            self.x="could not geocode"
            self.y="could not geocode"
#use the da cursor they are more efficient
with arcpy.da.UpdateCursor(fc,(field1,latitude,longitude)) as cursor:
    for row in cursor:
        geo=geolocate(row[0])
        geo.latlongs()
        print geo.y +' '+geo.x
        row[1]=geo.y
        row[2]=geo.x
        cursor.updateRow(row)
4
  • thank you! Is there a way to output the results of the geolocation into 2 separate fields?? Like, put the lat in one field, and the long in another?
    – evand
    Apr 16, 2018 at 9:33
  • @evand please accept my answer if it worked!
    – ziggy
    Apr 18, 2018 at 13:23
  • how do I "accept" your answer??
    – evand
    Apr 22, 2018 at 15:16
  • There should be a check mark on the left of my question, click it, it turns green
    – ziggy
    Apr 22, 2018 at 15:52
0

I have just a clarification to do. Since the geocode only accepts 2500 per day (free) and then for the rest, it is paid version. So, I would suggest to go for Selenium webdriver or RoboBrowser would be much more efficient.

What you can do is there are websites in which you can plugin addresses and latlongs are retrieved and these are completely free. The documentation is linked below. Hope this helps :)

Selenium: https://www.seleniumhq.org/projects/webdriver/ RoboBrowser: https://robobrowser.readthedocs.io/en/latest/readme.html

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.