根据经纬度坐标,如何确定城市/国家?

169
例如,如果我们有这些坐标集。
"latitude": 48.858844300000001,
"longitude": 2.2943506,

我们怎样才能找到城市/国家信息?


2
你可能需要某种类型的数据库。我会尝试自己使用Google Maps API……它支持纬度/经度。 - beatgammit
1
请参阅**从纬度经度获取国家**。 - hippietrail
16个回答

193

另一个选项:

  • http://download.geonames.org/export/dump/下载城市数据库
  • 将每个城市添加为纬度/经度到城市的映射,并将其添加到空间索引中,例如R-Tree(某些数据库也具有此功能)
  • 使用最近邻搜索查找任何给定点的最近城市

优点:

  • 不依赖于可用的外部服务器
  • 非常快速(轻松处理数千次查询每秒)

缺点:

  • 不会自动更新
  • 如果想要区分最近的城市距离很远的情况,则需要额外的代码
  • 在极地和国际日期线附近可能会产生奇怪的结果(尽管这些地方没有城市)

6
对于城市内部的位置,查询结果可能会出现奇怪的情况。例如,在罗马的某些地点进行查询时,可能会返回“梵蒂冈城”——这取决于数据库中每个位置所指定的纬度/经度。 - Zephyr was a Friend of Mine
2
他们还有一个REST API,看起来相当不错:http://api.geonames.org/findNearbyJSON?lat=9.9271&lng=-84.082&username=demo - jeudyx
14
一个例子会非常有价值。 - Hack-R
1
@joedotnot:你怎么可能认为它看起来“不活跃”呢?论坛中有昨天的评论,三月份的博客文章,首页上还有一个“最近修改”的链接,里面充满了今天的更新内容。 - Michael Borgwardt
如何提供一个小例子来展示如何进行这个搜索? - GuidoG
显示剩余3条评论

112

接受这个答案,因为这是我最终选择的 :) Michael的回答也绝对是一个好选择! - meow
5
谷歌的逆地理编码只有在与谷歌地图一起使用时才被允许。如果您想要一个没有这些限制的解决方案(虽然是商业性质的,并且仅针对美国城市),请查看:http://askgeo.com。 - James D
MapQuest API是另一个选择,因为它在某些情况下没有速率限制,并且对于各种地理编码需求具有非常高的速率限制。 - Tom
4
“免费”一词是有争议的,它只在某些限制下才是免费的。 - Petah
1
@JamesD:API政策指出,如果您在地图上显示数据,则必须是Google地图,但您不必在地图上(或根本不)显示它。 - user276648

65
你需要 geopy
pip install geopy

然后:
from geopy.geocoders import Nominatim
geolocator = Nominatim(user_agent="my-app")
location = geolocator.reverse("48.8588443, 2.2943506")

print(location.address)

获取更多信息:
print (location.raw)

{'place_id': '24066644', 'osm_id': '2387784956', 'lat': '41.442115', 'lon': '-8.2939909', 'boundingbox': ['41.442015', '41.442215', '-8.2940909', '-8.2938909'], 'address': {'country': 'Portugal', 'suburb': 'Oliveira do Castelo', 'house_number': '99', 'city_district': 'Oliveira do Castelo', 'country_code': 'pt', 'city': 'Oliveira, São Paio e São Sebastião', 'state': 'Norte', 'state_district': 'Ave', 'pedestrian': 'Rua Doutor Avelino Germano', 'postcode': '4800-443', 'county': 'Guimarães'}, 'osm_type': 'node', 'display_name': '99, Rua Doutor Avelino Germano, Oliveira do Castelo, Oliveira, São Paio e São Sebastião, Guimarães, Braga, Ave, Norte, 4800-443, Portugal', 'licence': 'Data © OpenStreetMap contributors, ODbL 1.0. http://www.openstreetmap.org/copyright'}

3
有任何限制吗?这似乎是最快的方法。使用这种方法是否有任何不利之处,相较于@Michael的方法? - Satys
1
需要一个外部服务。 - maxbachmann
这是一个很好的方法,但我只需要县级行政区划,所以我需要精确地址。我希望有一种方法可以返回县级行政区划。 - Fatemeh Asgarinejad

29

一个开源的替代方案是来自Open Street Map的Nominatim。您只需要在URL中设置变量,它就会返回该位置的城市/国家。请查看以下链接获取官方文档: Nominatim


7
请注意,Nominatim使用政策 https://operations.osmfoundation.org/policies/nominatim/ 规定了每秒最多只能发送一次请求,因此仅适用于临时查询。 - Matthew Wise

23

我正在寻找类似的功能,之前看到在回复中分享了数据“http://download.geonames.org/export/dump/”(感谢分享,这是一个很棒的资源),并基于cities1000.txt数据实现了一个服务。

您可以在以下链接中查看其运行情况: http://scatter-otl.rhcloud.com/location?lat=36&long=-78.9 (链接已失效) 只需更改您的位置的纬度和经度即可。

它部署在OpenShift(红帽平台)上。第一次调用可能需要一些时间,但通常性能是令人满意的。 请随意使用此服务…

此外,您可以在以下链接中找到该项目的源代码: https://github.com/turgos/Location


它不能正常工作。如果无法获取城市,则会搜索最近的已知城市。这是一个例子:http://scatter-otl.rhcloud.com/location?lat=17.1565111&long=-61.8495595 它显示“Basseterre”而不是“Saint John”... - smartmouse
1
没错。该算法在数据集中搜索最接近的可用城市。对于上述部署的服务器,我使用了“cities1000.txt”。它只包含主要城市。源代码可在 https://github.com/turgos/Location 上找到。您可以从“http://download.geonames.org/export/dump/”获取更详细的数据开始自己的项目。 - turgos
似乎cities1000.txt是可用的更详细数据。我对吗? - smartmouse

9

我曾使用Geocoder,这是一个很好的Python库,支持多个提供者,包括Google、Geonames和OpenStreetMaps等,只是举了几个例子。我尝试使用GeoPy库,但它经常会超时。开发自己的GeoNames代码并不是最好的时间利用方式,你可能最终得到不稳定的代码。我的经验是,Geocoder非常简单易用,并且有足够好的文档。下面是一些示例代码,用于按纬度和经度查找城市,或通过城市名称查找纬度/经度。

import geocoder

g = geocoder.osm([53.5343609, -113.5065084], method='reverse')
print g.json['city'] # Prints Edmonton

g = geocoder.osm('Edmonton, Canada')
print g.json['lat'], g.json['lng'] # Prints 53.5343609, -113.5065084

谢谢分享,但它并不适用于所有坐标。坐标的位数需要特定大小吗? - Fatemeh Asgarinejad
我知道的坐标规则是纬度在前,经度在后。你能提供一下这个规则不适用的坐标数值吗? - Hamman Samuel
1
我相信我正确选择了经度和纬度。我有成千上万个坐标,其中一个随机坐标无法使用。现在没问题了。我采用了另一种方法。感谢您的回复。 - Fatemeh Asgarinejad
1
欢迎。很好奇您采用了什么方法?如果比“geocoder”更好,我也想尝试一下! - Hamman Samuel
1
我使用了以下代码:from geopy.geocoders import Nominatim geolocator = Nominatim() location = geolocator.reverse("41.4721, -72.6311")print(location.address)它会返回完整的地址,然后我从中筛选出县。 - Fatemeh Asgarinejad
1
谢谢,我曾经使用过一个大型数据集,在2017年使用GeoPy时遇到了很多超时问题。也许三年后他们放宽了限制,这是个好消息! - Hamman Samuel

7
我知道这个问题很老,但我一直在处理同样的问题,我找到了一个非常高效和方便的包reverse_geocoder,由Ajay Thampi开发。 代码可以在这里找到。它基于K-D树的并行实现,对大量点非常有效(获取100,000个点只需几秒钟)。
它基于已被@turgos提到的数据库。
如果您的任务是快速查找一组坐标的国家和城市,这是一个绝佳的工具。

5
我花了大约30分钟的时间在尝试寻找JavaScript代码示例来完成这个任务。我没有找到一个快速明确的答案来回答你的问题。所以...我自己写了一个。希望人们可以使用它而不必深入挖掘API或盯着他们不知道如何阅读的代码。哈,如果没有其他的,我可以引用这篇文章为我的东西提供参考。很好的问题,感谢讨论区!
这是利用Google API实现的。
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?key=<YOURGOOGLEKEY>&sensor=false&v=3&libraries=geometry"></script>

.

//CHECK IF BROWSER HAS HTML5 GEO LOCATION
if (navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(function (position) {

        //GET USER CURRENT LOCATION
        var locCurrent = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);

        //CHECK IF THE USERS GEOLOCATION IS IN AUSTRALIA
        var geocoder = new google.maps.Geocoder();
            geocoder.geocode({ 'latLng': locCurrent }, function (results, status) {
                var locItemCount = results.length;
                var locCountryNameCount = locItemCount - 1;
                var locCountryName = results[locCountryNameCount].formatted_address;

                if (locCountryName == "Australia") {
                    //SET COOKIE FOR GIVING
                    jQuery.cookie('locCountry', locCountryName, { expires: 30, path: '/' }); 
                }
        });
    }
}

3
这真的取决于您有什么技术限制。一种方法是使用带有感兴趣国家和城市轮廓线的空间数据库。通过轮廓线,我指的是将国家和城市存储为空间类型多边形。您的坐标集可以转换为空间类型点,并对多边形进行查询,以获取点所在的国家/城市名称。
以下是一些支持空间类型的数据库: SQL server 2008, MySQL, postGIS - postgreSQL的扩展和Oracle
如果您不想拥有自己的数据库,而是希望使用服务,那么您可以使用Yahoo的GeoPlanet。对于服务方法,您可能需要查看thisgis.stackexchange.com上的答案,该答案涵盖了解决问题所需的服务可用性。

2

Loc2country 是一个基于 Golang 的工具,用于返回给定位置坐标(lat/lon)的 ISO alpha-3 国家代码。它以微秒级响应。它使用 geohash 到国家的映射。

geohash 数据是使用 georaptor 生成的。

我们在此工具中使用了 6 级 geohash,即大小为 1.2km x 600m 的方框。


我本以为这是一个CLI程序,而不是一个服务器。 - Sridhar Sarnobat

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