如何使用Python获取经纬度

49

我正在尝试通过下面的脚本检索一个物理地址的经度和纬度。但是我遇到了错误。我已经安装了 Google Maps。

#!/usr/bin/env python
import urllib,urllib2


"""This Programs Fetch The Address"""

from googlemaps import GoogleMaps


address='Mahatma Gandhi Rd, Shivaji Nagar, Bangalore, KA 560001'

add=GoogleMaps().address_to_latlng(address)
print add

输出:

Traceback (most recent call last):
  File "Fetching.py", line 12, in <module>
    add=GoogleMaps().address_to_latlng(address)
  File "/usr/local/lib/python2.7/dist-packages/googlemaps.py", line 310, in address_to_latlng
    return tuple(self.geocode(address)['Placemark'][0]['Point']['coordinates'][1::-1])
  File "/usr/local/lib/python2.7/dist-packages/googlemaps.py", line 259, in geocode
    url, response = fetch_json(self._GEOCODE_QUERY_URL, params=params)
  File "/usr/local/lib/python2.7/dist-packages/googlemaps.py", line 50, in fetch_json
    response = urllib2.urlopen(request)
  File "/usr/lib/python2.7/urllib2.py", line 127, in urlopen
    return _opener.open(url, data, timeout)
  File "/usr/lib/python2.7/urllib2.py", line 407, in open
    response = meth(req, response)
  File "/usr/lib/python2.7/urllib2.py", line 520, in http_response
    'http', request, response, code, msg, hdrs)
  File "/usr/lib/python2.7/urllib2.py", line 445, in error
    return self._call_chain(*args)
  File "/usr/lib/python2.7/urllib2.py", line 379, in _call_chain
    result = func(*args)
  File "/usr/lib/python2.7/urllib2.py", line 528, in http_error_default
    raise HTTPError(req.get_full_url(), code, msg, hdrs, fp)
urllib2.HTTPError: HTTP Error 403: Forbidden

2
你可能需要设置API密钥。像这样 GoogleMaps(api_key)。在这里查看文档http://py-googlemaps.sourceforge.net/。 - nikora
我尝试过了,但仍然得到相同的错误。 - user3008712
可能是一个重复的问题: 当使用经纬度进行地理编码时,遇到403禁止错误 - geocodezip
11个回答

59

你使用的googlemaps包不是官方版本,也没有使用Google地图API v3,这是Google最新版本的API。

您可以使用Google的geocode REST API从地址获取坐标。以下是一个示例。

import requests

response = requests.get('https://maps.googleapis.com/maps/api/geocode/json?address=1600+Amphitheatre+Parkway,+Mountain+View,+CA')

resp_json_payload = response.json()

print(resp_json_payload['results'][0]['geometry']['location'])

28
这个答案需要使用API密钥。 - edesz
API密钥是免费的还是需要付费? - Tommy Lees
1
据我所知,这需要一个密钥才能使用并且是收费的。我希望有一个免费的解决方案。 - saran3h
请参考下面的答案,获取无需 API 密钥的免费解决方案。 - Hamish Anderson
如果您有API密钥,请在URL末尾添加它,就像这样: response = requests.get('https://maps.googleapis.com/maps/api/geocode/json?address=1600+Amphitheatre+Parkway,+Mountain+View,+CA&key=<YOUR_KEY>') - Prateek

43
对于一个不需要API密钥或外部库的Python脚本,您可以查询Nominatim服务,该服务会查询Open Street Map数据库。
有关如何使用它的更多信息,请参阅https://nominatim.org/release-docs/develop/api/Search/
下面是一个简单的示例:
import requests
import urllib.parse

address = 'Shivaji Nagar, Bangalore, KA 560001'
url = 'https://nominatim.openstreetmap.org/search?q=' + urllib.parse.quote(address) +'?format=json'

response = requests.get(url).json()
print(response[0]["lat"])
print(response[0]["lon"])

你能简单解释一下它是如何工作的吗? - Santiago
2
在选择Nominatim/OSM API之前,请阅读此API的使用政策: https://operations.osmfoundation.org/policies/nominatim/ - naaman
9
对于那些使用这段代码的人,我只想提醒一下,它并不总是会产生响应。这样我就可以帮助大家节省时间了。 - x0xRumbleLorex0x
1
更新了答案,现在应该可以正常工作了。API的路径从/search/更改为/search?q=。请参考https://nominatim.openstreetmap.org/search/。 - undefined

26

尝试这段代码:

from geopy.geocoders import Nominatim
geolocator = Nominatim(user_agent="my_user_agent")
city ="London"
country ="Uk"
loc = geolocator.geocode(city+','+ country)
print("latitude is :-" ,loc.latitude,"\nlongtitude is:-" ,loc.longitude)

它不支持utf-8字符,只适用于拉丁字符集。有没有办法让它支持utf-8? - Mostafa Ghadimi
你不知道这有多有帮助...谢谢... - Mudit Bhatia
这在普通位置上不起作用,我已经尝试过地址列表,并获得了相当多的NoneType。 - Frank Jimenez

8

你也可以使用 Bing Maps API 的地理编码器。与仅适用于60%的地址的 Nominatim 不同,该 API 为我获取了所有地址的纬度和经度数据,并且它有一个相当不错的非商业用途免费版本(每年最多125,000个请求免费)。要获得免费API,请转到此处并单击“获取免费基本密钥”。获得 API 后,您可以在下面的代码中使用它:

import geocoder # pip install geocoder
g = geocoder.bing('Mountain View, CA', key='<API KEY>')
results = g.json
print(results['lat'], results['lng'])

结果中含有的信息远不止经度和纬度,请查看。


6
使用谷歌API、Python和Django获取纬度和经度的最简单方法。
# Simplest way to get the lat, long of any address.

# Using Python requests and the Google Maps Geocoding API.

        import requests

        GOOGLE_MAPS_API_URL = 'http://maps.googleapis.com/maps/api/geocode/json'

        params = {
            'address': 'oshiwara industerial center goregaon west mumbai',
            'sensor': 'false',
            'region': 'india'
        }

        # Do the request and get the response data
        req = requests.get(GOOGLE_MAPS_API_URL, params=params)
        res = req.json()

        # Use the first result
        result = res['results'][0]

        geodata = dict()
        geodata['lat'] = result['geometry']['location']['lat']
        geodata['lng'] = result['geometry']['location']['lng']
        geodata['address'] = result['formatted_address']

    print('{address}. (lat, lng) = ({lat}, {lng})'.format(**geodata))

# Result => Link Rd, Best Nagar, Goregaon West, Mumbai, Maharashtra 400104, India. (lat, lng) = (19.1528967, 72.8371262)

这个应该放在你的视图里还是模型里?另外,如果我想把经纬度存储在一个字段中,我该怎么做? - Doing Things Occasionally
4
这也需要一个 API 密钥,必须在参数中设置,例如 'key': 'AIza...' - Christoph Lösch
你为什么需要Django? - 89f3a1c

5

正如 @WSaitama 所说,geopy 很好用,不需要验证。要下载它: https://pypi.org/project/geopy/。使用示例:

from geopy.geocoders import Nominatim

address='Barcelona'
geolocator = Nominatim(user_agent="Your_Name")
location = geolocator.geocode(address)
print(location.address)
print((location.latitude, location.longitude))
#Barcelona, Barcelonès, Barcelona, Catalunya, 08001, España
#(41.3828939, 2.1774322)

5

你好,这里是我最常用的方法,用于获取物理地址的纬度和经度信息。 注意: 请使用空值填充NaNdf.adress.fillna('')

from geopy.exc import GeocoderTimedOut
# You define col corresponding to adress, it can be one
col_addr = ['street','postcode','town']
geocode = geopy.geocoders.BANFrance().geocode  

def geopoints(row):
    search=""
    for x in col_addr:
        search = search + str(row[x]) +' '

    if search is not None:
        print(row.name+1,end="\r")
        try:
            search_location = geocode(search, timeout=5)
            return search_location.latitude,search_location.longitude
        except (AttributeError, GeocoderTimedOut):
            print("Got an error on index : ",row.name)
            return 0,0


print("Number adress to located /",len(df),":")
df['latitude'],df['longitude'] = zip(*df.apply(geopoints, axis=1))

注意:我使用BANFrance()作为API,您可以在此处找到其他APIGeocoders


4

我在这个话题中找到了一个解决方案,但它对我不起作用,所以我进行了调整并使其正常工作。���需令牌。

要进一步了解,请参阅文档:https://nominatim.org/release-docs/latest/api/Search/

以下是代码。

import requests
import urllib.parse

city = "Paris"
country = "France"
url = "https://nominatim.openstreetmap.org/?addressdetails=1&q=" + city + "+" + country +"&format=json&limit=1"

response = requests.get(url).json()
print(response[0]["lat"])
print(response[0]["lon"])

输出:

48.8566969 2.3514616


1

以下是使用geopypositionstack API作为备选方案的nominatim解决方案。

Positionstack API免费支持每月最多25000个请求。

import requests

from geopy.geocoders import Nominatim

geolocator = Nominatim(user_agent='myapplication')

def get_nominatim_geocode(address):
    try:
      location = geolocator.geocode(address)
      return location.raw['lon'], location.raw['lat']
    except Exception as e:
        # print(e)
        return None, None

def get_positionstack_geocode(address):
  BASE_URL = "http://api.positionstack.com/v1/forward?access_key="
  API_KEY = "YOUR_API_KEY"
  
  url = BASE_URL +API_KEY+'&query='+urllib.parse.quote(address)
  try:
      response = requests.get(url).json()
      # print( response["data"][0])
      return response["data"][0]["longitude"], response["data"][0]["latitude"]
  except Exception as e:
      # print(e)
      return None,None

def get_geocode(address):
  long,lat = get_nominatim_geocode(address)
  if long == None:
    return get_positionstack_geocode(address)
  else:
    return long,lat

address = "50TH ST S"

get_geocode(address)

输出:

('-80.2581662', '26.6077474'

您可以直接使用nominatim,而无需使用geopy客户端。

import requests
import urllib

def get_nominatim_geocode(address):
    url = 'https://nominatim.openstreetmap.org/search/' + urllib.parse.quote(address) + '?format=json'
    try:
        response = requests.get(url).json()
        return response[0]["lon"], response[0]["lat"]
    except Exception as e:
        # print(e)
        return None, None

1

你尝试过使用 Geopy 库吗?https://pypi.org/project/geopy/

它适用于 Python 2.7 至 3.8 版本。此外,它还支持 OpenStreetMap Nominatim、Google 地理编码 API(V3)等。

希望它能对你有所帮助。


此外,它非常易于使用。 - Wsaitama

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接