Учитывая координаты широты и долготы, как мы можем узнать город / страну?


143

Например, если у нас есть этот набор координат

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

Как узнать город / страну?


2
Вам, вероятно, понадобится какая-то база данных. Я бы сам попробовал поиграть с Google Maps API ... он поддерживает широту и долготу.
beatgammit

Ответы:


97

Бесплатный API Google Geocoding предоставляет эту услугу через HTTP REST API. Обратите внимание: использование и скорость API ограничены , но вы можете заплатить за неограниченный доступ.

Попробуйте эту ссылку, чтобы увидеть пример вывода (это в json, вывод также доступен в XML)

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


принять это, потому что это тот, к которому я в конечном итоге иду :) Ответ Майкла, безусловно, отличный вариант!
ming yeow

5
Обратное геокодирование Google разрешено только в сочетании с Google Map. Если вам нужно решение, не имеющее таких ограничений (хотя оно коммерческое и доступно
Джеймс Д.

mapquest api - еще один вариант, поскольку в некоторых случаях он не имеет ограничений по скорости и очень высоких ограничений по скорости для различных нужд геокодирования.
Том

2
бесплатно спорно, он свободен только в определенных пределах.
Петах

@JamesD: политика API гласит, что если вы отображаете данные на карте, то это должна быть карта Google, но вам не нужно отображать ее на карте (или вообще).
user276648

177

Другой вариант:

  • Загрузите базу данных городов с http://download.geonames.org/export/dump/
  • Добавьте каждый город как широту / долготу -> Сопоставление города с пространственным индексом, таким как R-Tree (некоторые БД также имеют такую ​​функциональность)
  • Используйте поиск ближайшего соседа, чтобы найти ближайший город для любой заданной точки

Преимущества:

  • Не зависит от доступности внешнего сервера
  • Очень быстро (легко выполняет тысячи поисков в секунду)

Недостатки:

  • Не обновляется автоматически
  • Требуется дополнительный код, если вы хотите отличить случай, когда ближайший город находится в нескольких десятках миль.
  • Может давать странные результаты возле полюсов и международной линии перемены дат (хотя в этих местах все равно нет городов

5
Также будет давать странные результаты для городов в городах, например, некоторые места в Риме могут возвращать «Ватикан» - в зависимости от широты и долготы, указанных в базе данных для каждого.
Ноэль Абрахамс

2
У них также есть REST api и они выглядят довольно прилично: api.geonames.org/…
jeudyx

8
Пример был бы бесценным
Hack-R

GeoNames также предлагает бесплатный веб-сервис, который просто великолепен!
mcont 07

1
@joedotnot: как он может показаться вам "неактивным"? На форуме есть обсуждения со вчерашними комментариями, есть запись в блоге за март, и есть ссылка «последние изменения» прямо там, на главной странице, которая полна обновлений с сегодняшнего дня .
Майкл Боргвардт,

48

Тебе нужно 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'}

2
Есть ли у этого ограничения? Кажется, это самый быстрый подход. Может ли быть какая-то причина не использовать это над подходом @Michael?
Satys

1
ну, это требует внешнего сервиса
maxbachmann

Это отличный подход, но мне просто нужны округа, поэтому мне нужно уточнить адрес. Я бы хотел, чтобы был способ вернуть округа.
Fatemeh Asgarinejad

22

Альтернативой с открытым исходным кодом является Nominatim от Open Street Map. Все, что вам нужно сделать, это установить переменные в URL-адресе, и он вернет город / страну этого местоположения. Пожалуйста, проверьте следующую ссылку для получения официальной документации: Nominatim


3
Обратите внимание, что в политике использования Nominatim operations.osmfoundation.org/policies/nominatim указана максимальная скорость - один запрос в секунду, поэтому она действительно подходит только для специальных запросов.
Matthew Wise

22

Я искал аналогичную функциональность и увидел данные « http://download.geonames.org/export/dump/ », опубликованные в предыдущем ответе (спасибо, что поделились, это отличный источник), и реализовал сервис на основе по данным cities1000.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» ...
smartmouse

1
Это правильно. алгоритм выполняет поиск ближайшего города, доступного в наборе данных. Для развернутого выше сервера я использовал «cities1000.txt». В нем есть только крупные города. Исходный код доступен на github.com/turgos/Location . Вы можете начать свой собственный с более подробными данными на сайте " download.geonames.org/export/dump ".
turgos 01

Похоже, что файл cities1000.txt - это более подробные данные. Я прав?
smartmouse

8

Я использовал Geocoder , хорошую библиотеку Python, которая поддерживает несколько поставщиков, включая Google, Geonames и OpenStreetMaps, и это лишь некоторые из них . Я пробовал использовать библиотеку GeoPy, и она часто дает таймауты. Разработка собственного кода для GeoNames - не лучшее использование вашего времени, и вы можете получить нестабильный код. По моему опыту, геокодер очень прост в использовании и имеет достаточно хорошую документацию. . Ниже приведен пример кода для поиска города по широте и долготе или поиска широты / долготы по названию города.

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

1
Я считаю, что правильно выбрал долготу и широту. У меня есть тысячи координат, из которых случайная координата не работает. Теперь все в порядке. Я использовал другой подход. Спасибо за ваш ответ.
Fatemeh Asgarinejad

1
Добро пожаловать. Хотите узнать, какой подход сработал для вас? Если лучше geocoder, то и сам хочу попробовать!
Хамман Самуэль,

1
Я использовал это: from geopy.geocoders import Nominatim geolocator = Nominatim () location = geolocator.reverse ("41.4721, -72.6311") print (location.address) Он дает полный адрес, а затем я отфильтровываю округ по нему.
Fatemeh Asgarinejad

1
Спасибо, я работал с большим набором данных, и в 2017 году использование GeoPy принесло мне много тайм-аутов. Возможно, через 3 года они ослабили свои ограничения, так что это здорово!
Хамман Сэмюэл

5

Я потратил около 30 минут, пытаясь найти пример кода, как это сделать в Javascript. Я не смог найти четкого ответа на поставленный вами вопрос. Итак ... Я сделал свой собственный. Надеюсь, люди смогут использовать это, не копаясь в API или не глядя на код, который они не знают, как читать. Ха, если уж на то пошло, я могу сослаться на этот пост для своего собственного материала .. Хороший вопрос и спасибо за обсуждение на форуме!

Это использует API Google.

<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: '/' }); 
                }
        });
    }
}

5

Я знаю, что этот вопрос действительно старый, но я работал над той же проблемой и нашел чрезвычайно эффективный и удобный пакет reverse_geocoder, созданный Аджаем Темпи. Код доступен здесь . Он основан на распараллеленной реализации деревьев KD, что чрезвычайно эффективно для большого количества точек (мне потребовалось несколько секунд, чтобы получить 100000 точек.

Это основано на этом базе данных, уже выделенной @turgos.

Если ваша задача - быстро найти страну и город по списку координат, это отличный инструмент.


3

Это действительно зависит от того, какие технологические ограничения у вас есть.

Один из способов - иметь пространственную базу данных с контуром интересующих вас стран и городов. Под контуром я подразумеваю, что страны и города хранятся как многоугольники пространственного типа. Ваш набор координат можно преобразовать в точку пространственного типа и запросить у полигонов, чтобы получить название страны / города, в котором расположена точка.

Вот некоторые из баз данных, которые поддерживают пространственный тип: SQL server 2008 , MySQL , postGIS - расширение postgreSQL и Oracle .

Если вы хотите использовать сервис вместо собственной базы данных, вы можете использовать Yahoo GeoPlanet . Что касается сервисного подхода, вы можете проверить этот ответ на gis.stackexchange.com , который описывает доступность сервисов для решения вашей проблемы.


1

Вы можете использовать Google Geocoding 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;
}

если я хочу только административную_зону_уровень_ 3 или местность (если административная_зона_уровня_ 3 недоступна), какую из них мне следует изменить? новый для PHP ..
Август

1

Если вы используете Google Places API, вот как вы можете получить страну и город из объекта места с помощью Javascript:

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;
  }
}

1

Loc2country - это инструмент на основе Golang, который возвращает код страны ISO alpha-3 для заданных координат местоположения (широта / долгота). Он отвечает за микросекунды. Он использует геохеш для карты страны.

Данные геохеша генерируются с помощью геораптора .

Мы используем геохеш на уровне 6 для этого инструмента, то есть коробки размером 1,2 км x 600 м.



0

Пожалуйста, проверьте ответ ниже. Меня устраивает

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;
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.