【问题标题】:Given the lat/long coordinates, how can we find out the city/country?给定纬度/经度坐标,我们如何找出城市/国家?
【发布时间】:2011-09-03 18:48:05
【问题描述】:

例如,如果我们有这些坐标集

"latitude": 48.858844300000001,
"longitude": 2.2943506,

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

【问题讨论】:

标签: geolocation geocoding geospatial geo


【解决方案1】:

另一种选择:

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

优点:

  • 不依赖于可用的外部服务器
  • 非常快(每秒可轻松进行数千次查找)

缺点:

  • 不会自动更新
  • 如果要区分最近的城市在几十英里之外的情况,需要额外的代码
  • 在两极和国际日期变更线附近可能会给出奇怪的结果(尽管这些地方并没有任何城市

【讨论】:

  • 还会为城市中的城市提供奇怪的结果,例如罗马的某些位置可能会返回“梵蒂冈城”——这取决于数据库中为每个位置指定的纬度/经度。
  • 他们还有一个 REST api,看起来相当不错:api.geonames.org/…
  • 一个非常宝贵的例子
  • GeoNames 还提供了一个非常棒的免费网络服务!
  • @joedotnot:在你看来,它怎么可能看起来“不活跃”?论坛昨天和cmet有讨论,3月份有一篇博客,主页上有一个“最近的修改”链接,里面全是今天的更新。
【解决方案2】:

免费的Google Geocoding API 通过 HTTP REST API 提供此服务。请注意,API 是usage and rate limited,但您可以付费无限访问。

试试这个链接看看输出的例子(这是在 json,输出也可以在 XML 中)

https://maps.googleapis.com/maps/api/geocode/json?latlng=40.714224,-73.961452&sensor=true

【讨论】:

  • 接受这一点,因为这是我最终想要的:)迈克尔的回答当然是一个不错的选择!
  • Google 的反向地理编码仅允许与 Google 地图结合使用。如果您想要一个没有此类限制的解决方案(尽管它是商业的并且只有美国城市),请查看:askgeo.com
  • mapquest api 是这里的另一种选择,因为它在某些情况下没有速率限制,并且对于各种地理编码需求有非常高的速率限制。
  • free 值得商榷,它只有在一定的限制下才免费。
  • @JamesD:API policies 声明如果您在地图上显示数据,那么它必须是谷歌地图,但您不必在地图上显示(或根本不显示) )。
【解决方案3】:

你需要geopy

pip install geopy

然后:

from geopy.geocoders import Nominatim
geolocator = Nominatim()
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'}

【讨论】:

  • 这个有限制吗?这似乎是最快的方法。有什么理由不使用 @Michael 的方法吗?
  • 它需要外部服务
  • 这是一个很好的方法,但是我只需要县,所以我需要细化地址。我希望有办法回馈县。
【解决方案4】:

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

【讨论】:

【解决方案5】:

我在找一个类似的功能,看到之前回复分享的数据“http://download.geonames.org/export/dump/”(谢谢分享,很好的来源),基于city1000.txt数据实现了一个服务。

你可以看到它运行在 http://scatter-otl.rhcloud.com/location?lat=36&long=-78.9 (链接失效) 只需更改您所在位置的纬度和经度即可。

它部署在 OpenShift(RedHat 平台)上。长时间空闲后的第一次调用可能需要一些时间,但通常性能令人满意。 随意使用此服务...

此外,您可以在以下位置找到项目源代码 https://github.com/turgos/Location.

【讨论】:

  • 它不能正常工作。如果无法获取城市,它会搜索最近的已知城市。这是一个例子:scatter-otl.rhcloud.com/… 它说“Basseterre”而不是“Saint John”...
  • 没错。该算法搜索数据集中可用的最近城市。对于上面部署的服务器,我使用了“cities1000.txt”。它只有主要城市。源代码可在github.com/turgos/Location 获得。您可以从“download.geonames.org/export/dump”中获取更详细的数据开始自己的尝试。
  • 看来 city1000.txt 是更详细的可用数据。我说的对吗?
【解决方案6】:

我使用了Geocoder,这是一个很好的 Python 库,支持多个提供程序,包括 Google、Geonames 和 OpenStreetMaps,到 mention just a few。我试过使用 GeoPy 库,但它经常超时。为 GeoNames 开发您自己的代码并不是对您时间的最佳利用,您最终可能会得到不稳定的代码。根据我的经验,地理编码器使用起来非常简单,并且足够好 documentation。下面是一些通过经纬度查找城市,或通过城市名称查找纬度/经度的示例代码。

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

【讨论】:

  • 感谢分享,但不适用于所有坐标。坐标的位数是否需要特定大小?
  • 我相信我正确选择了经度和纬度。我有数千个坐标,其中随机坐标不起作用。现在好了。我使用了另一种方法。感谢您的回复。
  • 欢迎。想知道哪种方法对您有用吗?如果比geocoder好,我也想自己试试!
  • 我用了这个: from geopy.geocoders import Nominatim geolocator = Nominatim() location = geolocator.reverse("41.4721, -72.6311") print(location.address) 它给出了整个地址,然后我从中过滤县。
  • 谢谢,我使用了一个大型数据集,在 2017 年,使用 GeoPy 让我遇到了很多超时。也许 3 年后他们放宽了限制,所以很高兴知道!
【解决方案7】:

我知道这个问题真的很老了,但我一直在研究同样的问题,我发现了一个非常高效和方便的包,reverse_geocoder,由 Ajay Thampi 构建。 代码可用here。它基于 K-D 树的并行实现,这对于大量点非常有效(我花了几秒钟才获得 100,000 个点。

它基于@turgos 已突出显示的this 数据库。

如果您的任务是快速找到坐标列表中的国家和城市,这是一个很棒的工具。

【讨论】:

    【解决方案8】:

    我花了大约 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: '/' }); 
                    }
            });
        }
    }
    

    【讨论】:

      【解决方案9】:

      这真的取决于你有什么技术限制。

      一种方法是拥有一个空间数据库,其中包含您感兴趣的国家和城市的轮廓。轮廓是指国家和城市存储为空间类型多边形。您的坐标集可以转换为空间类型点并针对多边形进行查询以获取该点所在的国家/城市名称。

      以下是一些支持空间类型的数据库:SQL server 2008、MySQL、postGIS - postgreSQL 和 Oracle 的扩展。

      如果您想使用服务而不是拥有自己的数据库,您可以使用雅虎的GeoPlanet。对于服务方法,您可能需要查看gis.stackexchange.com 上的this 答案,其中涵盖了用于解决您的问题的服务的可用性。

      【讨论】:

        【解决方案10】:

        您可以使用 Google 地理编码 API

        Bellow 是返回地址、城市、州和国家/地区的 php 函数

        public function get_location($latitude='', $longitude='')
        {
            $geolocation = $latitude.','.$longitude;
            $request = 'http://maps.googleapis.com/maps/api/geocode/json?latlng='.$geolocation.'&sensor=false'; 
            $file_contents = file_get_contents($request);
            $json_decode = json_decode($file_contents);
            if(isset($json_decode->results[0])) {
                $response = array();
                foreach($json_decode->results[0]->address_components as $addressComponet) {
                    if(in_array('political', $addressComponet->types)) {
                            $response[] = $addressComponet->long_name; 
                    }
                }
        
                if(isset($response[0])){ $first  =  $response[0];  } else { $first  = 'null'; }
                if(isset($response[1])){ $second =  $response[1];  } else { $second = 'null'; } 
                if(isset($response[2])){ $third  =  $response[2];  } else { $third  = 'null'; }
                if(isset($response[3])){ $fourth =  $response[3];  } else { $fourth = 'null'; }
                if(isset($response[4])){ $fifth  =  $response[4];  } else { $fifth  = 'null'; }
        
        
                $loc['address']=''; $loc['city']=''; $loc['state']=''; $loc['country']='';
                if( $first != 'null' && $second != 'null' && $third != 'null' && $fourth != 'null' && $fifth != 'null' ) {
                    $loc['address'] = $first;
                    $loc['city'] = $second;
                    $loc['state'] = $fourth;
                    $loc['country'] = $fifth;
                }
                else if ( $first != 'null' && $second != 'null' && $third != 'null' && $fourth != 'null' && $fifth == 'null'  ) {
                    $loc['address'] = $first;
                    $loc['city'] = $second;
                    $loc['state'] = $third;
                    $loc['country'] = $fourth;
                }
                else if ( $first != 'null' && $second != 'null' && $third != 'null' && $fourth == 'null' && $fifth == 'null' ) {
                    $loc['city'] = $first;
                    $loc['state'] = $second;
                    $loc['country'] = $third;
                }
                else if ( $first != 'null' && $second != 'null' && $third == 'null' && $fourth == 'null' && $fifth == 'null'  ) {
                    $loc['state'] = $first;
                    $loc['country'] = $second;
                }
                else if ( $first != 'null' && $second == 'null' && $third == 'null' && $fourth == 'null' && $fifth == 'null'  ) {
                    $loc['country'] = $first;
                }
              }
              return $loc;
        }
        

        【讨论】:

        • 如果我只想要administration_area_level_3 或locality(如果没有administrator_area_level_3),我应该修改哪一个? php新手..
        【解决方案11】:

        如果您使用的是 Google 的 Places API,那么您可以使用 Javascript 从 place 对象获取国家和城市:

        function getCityAndCountry(location) {
          var components = {};
          for(var i = 0; i < location.address_components.length; i++) {
            components[location.address_components[i].types[0]] = location.address_components[i].long_name;
          }
        
          if(!components['country']) {
            console.warn('Couldn\'t extract country');
            return false;
          }
        
          if(components['locality']) {
            return [components['locality'], components['country']];
          } else if(components['administrative_area_level_1']) {
            return [components['administrative_area_level_1'], components['country']];
          } else {
            console.warn('Couldn\'t extract city');
            return false;
          }
        }
        

        【讨论】:

          【解决方案12】:

          Loc2country 是一个基于 Golang 的工具,它返回给定位置坐标(纬度/经度)的 ISO alpha-3 国家代码。它在微秒内响应。它使用地理哈希到国家地图。

          geohash 数据是使用georaptor 生成的。

          我们为此工具使用级别 6 的 geohash,即大小为 1.2km x 600m 的盒子。

          【讨论】:

          • 该死,我希望这是一个 CLI 程序而不是服务器。
          【解决方案13】:

          请检查以下答案。它对我有用

          if(navigator.geolocation) {
              navigator.geolocation.getCurrentPosition(function(position){
          
                  initialize(position.coords.latitude,position.coords.longitude);
              }); 
          }
          
          function initialize(lat,lng) {
              //directionsDisplay = new google.maps.DirectionsRenderer(rendererOptions);
              //directionsService = new google.maps.DirectionsService();
              var latlng = new google.maps.LatLng(lat, lng);
          
              //alert(latlng);
              getLocation(latlng);
          }
          
          function getLocation(latlng){
          
              var geocoder = new google.maps.Geocoder();
              geocoder.geocode({'latLng': latlng}, function(results, status) {
                      if (status == google.maps.GeocoderStatus.OK) {
                          if (results[0]) {
                              var loc = getCountry(results);
                              alert("location is::"+loc);
                          }
                      }
                  });
          
          }
          
          function getCountry(results)
          {
              for (var i = 0; i < results[0].address_components.length; i++)
              {
                  var shortname = results[0].address_components[i].short_name;
                  var longname = results[0].address_components[i].long_name;
                  var type = results[0].address_components[i].types;
                  if (type.indexOf("country") != -1)
                  {
                      if (!isNullOrWhitespace(shortname))
                      {
                          return shortname;
                      }
                      else
                      {
                          return longname;
                      }
                  }
              }
          
          }
          
          function isNullOrWhitespace(text) {
              if (text == null) {
                  return true;
              }
              return text.replace(/\s/gi, '').length < 1;
          }
          

          【讨论】:

            【解决方案14】:

            尽量减少库的数量。

            在他们的网站上获取使用 API 的密钥,然后在 http 请求中获取结果:

            curl -i -H "key: YOUR_KEY" -X GET https://api.latlong.dev/lookup?lat=38.7447913&long=-9.1625173
            

            【讨论】:

              猜你喜欢
              • 2021-11-23
              • 1970-01-01
              • 2014-06-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2012-12-04
              相关资源
              最近更新 更多