我目前正在开发一个对地址列表进行地理编码的脚本,以便为分析和可视化做好准备。这是我第一次使用Geocoding,所以我正在努力,不知道是否有什么明显的遗漏。我正在使用Google的Geocoding API。
我的(未优化)过程的大致轮廓是将DataFrame中包含地址的一列变成一个列表。然后,我使用列表理解法从那个列表中创建一个新的列表,其中每个元素都是我得到的数据的子集。
key = ...
city = "Long Beach"
state = "CA"
addresses = df["Address"].values.tolist()
geocodes = [geocode(x,city,state,key) for x in addresses]
我用于地理编码的实际函数如下。它接收了我的API密钥、地址和citystate参数,给出一个移动完整的地址。然后,它只是进行调用,并在响应中返回一个我正在寻找的三个元素的列表。
def geocode(address, city, state, key):
time.sleep(.05)
params = f"{address.lower()} {city}, {state}".replace(" ","+")
request_url = "https://maps.googleapis.com/maps/api/geocode/json?address="+params+f"&key={key}"
response = requests.get(request_url).json()
neighborhood = response["results"][0]["address_components"][2]["long_name"]
lat = response["results"][0]["geometry"]["location"]["lat"]
lon = response["results"][0]["geometry"]["location"]["lng"]
return [neighborhood, lat, lon]
当我运行它时,脚本会进展一段时间,然后失败。当它这样做时,跟踪回溯给我的异常,我包括在这个下面。到目前为止,我还没能找到关于这个问题可能是什么的信息,或者我应该如何接近诊断问题的Google的Geocoding API。他们给出了关于如何解释请求状态的信息,但是当我在检查失败前返回的状态时,所有的状态都是 'OK'
而他们都没有提供为什么连接关闭的指示。
RemoteDisconnected: Remote end closed connection without response
During handling of the above exception, another exception occurred:
ProtocolError Traceback (most recent call last)
----------
ProtocolError: ('Connection aborted.', RemoteDisconnected('Remote end closed connection without response'))
During handling of the above exception, another exception occurred:
ConnectionError Traceback (most recent call last)
----------
ConnectionError: ('Connection aborted.', RemoteDisconnected('Remote end closed connection without response'))
现在,我已经玩弄了它,并排除了一些事情,到目前为止:1.我已经成功地尝试了单次调用,并得到了我需要的东西。问题发生在我在一个列表上运行它的时候.2.我已经使用TQDM并打印了状态(在不同的点),脚本确实成功地进行了调用,取回数据,并在失败之前多次移动到下一个.3.我不认为这是一个速率限制的问题。这个API没有每日限制,只有每秒50次的查询限制。粗糙的 time.sleep(.05)
在我的功能中应该保持在20QPS左右,让我在这个极限之下。
有人知道我的问题是什么吗?或者有人能解释一下我应该做哪些额外的诊断?再次强调,我是地理编码的新手,而且我之前在使用我有经验的API时还没有遇到过这个问题,所以如果没有人能够找到问题,哪怕是帮助我了解发生了什么,以便我可以自己解决它,我也会非常感激。
尝试使用官方的googlemaps py模块。它使用 requests.Session
在引擎盖下,但我从来没有遇到过麻烦。你可能需要一些 multithreading
但如果你没有 "太多 "的地址,这应该可以做到。
import time
import logging
import googlemaps
key = '...'
gmaps_client = googlemaps.Client(key=key)
addresses = [
["8473 Manor Station Street", "Cartersville", "GA"],
["14 Edgewater Ave.", "Ottumwa", "IA"],
["42 Aspen Court", "San Diego", "CA"]
]
def geocode(address, city, state):
time.sleep(.05)
params = f"{address.lower()} {city}, {state}".replace(" ", "+")
try:
response = gmaps_client.geocode(params)[0]
neighborhood = response["address_components"][2]["long_name"]
lat = response["geometry"]["location"]["lat"]
lon = response["geometry"]["location"]["lng"]
return [neighborhood, lat, lon]
except Exception as e:
logging.error(e)
return [None, None, None]
geocodes = [geocode(*group) for group in addresses]
print(geocodes)