使用请求从谷歌距离矩阵api获取响应时出现连接错误

时间:2017-08-03 08:54:36

标签: python python-3.x google-maps-api-3 python-requests google-distancematrix-api

我正在尝试开发一些涉及在两个地理位置之间找到距离的东西。

源和目标有很多这样的组合,我将它循环传入google distance API。

我的部分代码:

key_list = [****,****,....]  #google key list
base_url = 'https://maps.googleapis.com/maps/api/distancematrix/json?'

for i in geocodes:
    for j in key_list:

        origin_part = 'origins=' + i[0] + "," + i[1]
        destination_part = '&destinations=' + i[2] + "," + i[3]
        api_url = base_url + origin_part + destination_part + key
        json_response = requests.get(api_url,timeout=10).json()
        if json_response["status"] == "OVER_QUERY_LIMIT":
            j += 1
            i -= 1

这只是我代码的一部分。

geocodes是包含子列表的嵌套列表

[[source_latitude,source_longitude,destination_latitude,destination_longitude],....]

代码运行正常一段时间,但过了一段时间,它给了我一个错误说:

HTTPSConnectionPool(host='maps.googleapis.com', port=443): Max retries exceeded with url: /maps/api/distancematrix/json?origins=xx,xx&destinations=xx,xx&key=xxxxx 
(Caused by NewConnectionError('<requests.packages.urllib3.connection.VerifiedHTTPSConnection object at 0x7f53350c50f0>: Failed to establish a new connection: [Errno -3] Temporary failure in name resolution',))

我也试过使用会话而不是请求,但同样的错误即将来临。

我想知道造成这个问题的原因是什么?

如何在不使用try-catch的情况下更好地纠正它。

2 个答案:

答案 0 :(得分:1)

我认为主要问题源于代码格式不正确的事实。它现在的设置方式,我不相信你能够防止这个错误。

  1. 嵌套for循环

    for i in geocodes:
        for j in key_list:
    

    geocodes是包含原点和目标坐标的列表列表,key_lists包含所有api密钥。这里的问题是geocodes是第一个for循环。实质上,key_list中的每个键都用于查找每个坐标对的距离矩阵。哪个是浪费api资源。

  2. 使用不同的api密钥

    api_url = base_url + origin_part + destination_part + key
    

    这行代码属于嵌套的for循环,并生成您的api url。问题在于它永远不会改变。最后一个元素是key。既然你说这只是代码片段,我们不知道key的含义是什么,但我认为它是一个在代码前面设置的静态api密钥。当它实际上应该是j时,它会切换键。

  3. 按错键切换

    if json_response["status"] == "OVER_QUERY_LIMIT":
        j+=1
        i-=1
    

    这行代码并不完全符合你的想法。它不会切换到for循环中的下一个j,然后返回i。这只会从其值中加1或减1,因为最终不会出现intsfloats错误。

  4. 相反,我建议您将代码更改为此。

    base_url = 'https://maps.googleapis.com/maps/api/distancematrix/json?'
    key_list = [****,****,....]  #google key list
    
    index,atEnd = 0,False
    for coords in geocodes:
        origin_part = 'origins=' + coords[0] + "," + coords[1]
        destination_part = '&destinations=' + coords[2] + "," + coords[3]
        api_url = base_url + origin_part + destination_part + key_list[index]
        json_response = requests.get(api_url,timeout=10).json()
    
        #Check if your over your daily limit, if so try the next key
        while json_response['status'] == 'OVER_QUERY_LIMIT':
            index += 1
             #if all keys used to max quotas, exit
            if index == len(key_list):
                atEnd = True
                break
            api_url = base_url + origin_part + destination_part + key_list[index]
            json_response = requests.get(api_url, timeout=10).json()
        print json_response
    
        #Exit main loop if all quotas reached
        if atEnd == True:
            print'All of your keys quotas have been used, try again tomorrow'
            break
    

    请注意,我并不精通map API的合法用途。但是,我很确定您所做的事情违反了Google的条款和条件,使用多个帐户超出了您的每日限制使用率。

    我建议在google开发者控制台上进行免费试用。他们为您提供300美元的信贷,使用他们的服务超出报价。

答案 1 :(得分:1)

正如其他回复中所述,您的摘录不是有效的代码,使用不同的密钥可能会滥用Google的T&amp; C'S。但是,这不是问题。

有什么问题?

requests错误中明确说明了您的问题。如您所见,您在urllib3中遇到的错误是here。您甚至没有达到向Google发送任何数据的程度。

查看特定邮件([Errno -3] Temporary failure in name resolution),系统会告诉您DNS无法将您的主机名(“maps.googleapis.com”)解析为IP地址。

这是一个众所周知的功能,requests(通过urllib3)始终调用getaddrinfo来解析主机名,因此您的操作系统不会缓存结果,或者您有一个不稳定的DNS服务器。有关详细信息,请参阅this SO thread

该怎么办?

第一种选择是尝试更可靠的DNS服务器 - 许多人在遇到此类问题时会使用Google的public DNS

如果这不起作用,您可以尝试自己进行DNS查找(即调用getaddrinfo)并缓存应用程序中的IP地址(然后使用该地址而不是URL中的主机名),或者您可以在计算机上安装DNS缓存。这些不会阻止DNS失败,但它们应该减少影响。