Dadas as coordenadas lat / long, como podemos descobrir a cidade / país?

141

Por exemplo, se tivermos esse conjunto de coordenadas

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

Como podemos descobrir a cidade / país?

ming yow
fonte
2
Você provavelmente precisará de um banco de dados de algum tipo. Eu tentaria jogar com a API do Google Maps ... ela suporta lat / long.
Beatgammit 28/05
1
Consulte também Obter país de longitude latitude
hippietrail

Respostas:

96

A API gratuita do Google Geocoding fornece esse serviço por meio de uma API HTTP REST. Observe que a API é de uso e taxa limitada , mas você pode pagar pelo acesso ilimitado.

Experimente este link para ver um exemplo da saída (isso é em json, a saída também está disponível em XML)

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

Kevin
fonte
aceitando isso, porque este é o que eu acabo escolhendo :) A resposta de Michael é certamente uma ótima opção!
ming yeow
5
A geocodificação reversa do Google é permitida apenas em conjunto com um mapa do Google. Se você deseja uma solução que não possui essas restrições (embora seja comercial e possua apenas cidades dos EUA), confira: askgeo.com
James D
A API do mapquest é outra opção aqui, pois, em alguns casos, não possui limites de taxa e limites muito altos para várias necessidades de geocodificação.
Tom
2
free é discutível, só é grátis sob certos limites.
Petah #
@ JamesD: as políticas da API afirmam que, se você exibir os dados em um mapa, deverá ser um mapa do Google, mas não precisará exibi-los em um mapa (ou mesmo).
user276648
173

Outra opção:

  • Faça o download do banco de dados de cidades em http://download.geonames.org/export/dump/
  • Adicione cada cidade como lat / long -> mapeamento da cidade a um índice espacial como uma R-Tree (alguns bancos de dados também têm a funcionalidade)
  • Use a pesquisa do vizinho mais próximo para encontrar a cidade mais próxima para qualquer ponto

Vantagens:

  • Não depende de um servidor externo para estar disponível
  • Muito rápido (facilmente faz milhares de pesquisas por segundo)

Desvantagens:

  • Não atualizado automaticamente
  • Requer código extra se você quiser distinguir o caso em que a cidade mais próxima fica a dezenas de quilômetros de distância
  • Pode dar resultados estranhos perto dos pólos e da linha de data internacional (embora, de qualquer maneira, não haja cidades nesses lugares
Michael Borgwardt
fonte
5
Também fornecerá resultados estranhos para cidades dentro das cidades; por exemplo, determinados locais em Roma podem retornar "Cidade do Vaticano" - dependendo da latitude / longitude especificada no banco de dados de cada uma.
21912 Noel Abrahams
1
Eles também têm uma API REST e parecem bastante decentes: api.geonames.org/…
jeudyx
8
Um exemplo teria sido de valor inestimável
Hack-R
GeoNames também oferece um serviço web gratuito, que é simplesmente incrível!
Mcont 7/12
Em 2020, o GeoNames.org parece praticamente inativo, alguém sabe se é atual? Em nenhum lugar o problema é que eles mencionam as datas da última atualização no site.
joedotnot 5/07
45

Você precisa geopy

pip install geopy

e depois:

from geopy.geocoders import Nominatim
geolocator = Nominatim()
location = geolocator.reverse("48.8588443, 2.2943506")

print(location.address)

para obter mais informações:

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'}
Farsheed
fonte
2
Existem limites para este? Esta parece ser a abordagem mais rápida. Poderia haver alguma razão para não usar isso na abordagem de @ Michael?
Satys 25/02/19
1
bem requer um serviço externo
maxbachmann
É uma ótima abordagem, no entanto, eu só preciso dos municípios, por isso preciso refinar o endereço. Eu gostaria que houvesse uma maneira de devolver os condados.
Fatemeh Asgarinejad
22

Uma alternativa de código aberto é o Nominatim do Open Street Map. Tudo o que você precisa fazer é definir as variáveis ​​em um URL e retornar a cidade / país desse local. Por favor, verifique o seguinte link para documentação oficial: Nominatim

Rega
fonte
3
Observe que a política de uso do Nominatim operations.osmfoundation.org/policies/nominatim indica uma taxa máxima de uma solicitação por segundo, portanto, é realmente adequada apenas para consultas ad-hoc.
Matthew Sábio
22

Eu estava procurando por uma funcionalidade semelhante e vi os dados " http://download.geonames.org/export/dump/ " compartilhados na resposta anterior (obrigado por compartilhar, é uma excelente fonte) e implementou um serviço baseado em nos dados cities1000.txt.

Você pode vê-lo rodando em http://scatter-otl.rhcloud.com/location?lat=36&long=-78.9 (link quebrado) Basta alterar a latitude e longitude dos seus locais.

É implantado no OpenShift (RedHat Platform). A primeira chamada após um longo período inativo pode levar algum tempo, mas geralmente o desempenho é satisfatório. Sinta-se livre para usar este serviço como quiser ...

Além disso, você pode encontrar a fonte do projeto em https://github.com/turgos/Location .

turgos
fonte
Não funciona adequadamente. Se não conseguir obter a cidade, procura uma cidade conhecida mais próxima. Aqui está um exemplo: scatter-otl.rhcloud.com/... Diz "Basseterre" em vez de "São João" ...
Smartmouse
1
Está correto. o algoritmo pesquisa a cidade mais próxima disponível no conjunto de dados. Para o servidor implantado acima, usei "cities1000.txt". Tem apenas as principais cidades. O código-fonte está disponível em github.com/turgos/Location . Você pode começar por conta própria com dados mais detalhados em " download.geonames.org/export/dump ".
turgos 01/12/2015
Parece que cities1000.txt são os dados mais detalhados disponíveis. Estou certo?
26916
8

Eu usei o Geocoder , uma boa biblioteca Python que suporta vários provedores, incluindo Google, Geonames e OpenStreetMaps, para mencionar apenas alguns . Eu tentei usar a biblioteca GeoPy, e muitas vezes obtém tempos limite. Desenvolver seu próprio código para o GeoNames não é o melhor uso do seu tempo e você pode acabar obtendo um código instável. O geocoder é muito simples de usar na minha experiência e possui uma documentação suficientemente boa . Abaixo está um código de exemplo para procurar cidade por latitude e longitude ou encontrar latitude / longitude por nome da cidade.

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
Hamman Samuel
fonte
Obrigado por compartilhar isso, mas ele não funciona para todas as coordenadas. O número de dígitos das coordenadas precisa estar em um tamanho específico?
Fatemeh Asgarinejad 24/01
1
Acredito que escolhi longitude e latitude corretamente. Eu tenho milhares de coordenadas das quais uma coordenada aleatória não funcionou. Está tudo bem agora. Eu usei outra abordagem. Obrigado pela sua resposta.
Fatemeh Asgarinejad 24/01
1
Bem-vinda. Curioso para saber qual abordagem funcionou para você? Se for melhor do que geocoder, eu também gostaria de tentar!
Hamman Samuel 24/01
1
Eu usei isso: from geopy.geocoders import Nominatim geolocator = Nominatim () location = geolocator.reverse ("41.4721, -72.6311") print (location.address) Fornece o endereço inteiro e depois filtrei o município a partir dele.
Fatemeh Asgarinejad 24/01
1
Obrigado, trabalhei com um grande conjunto de dados e, em 2017, o uso do GeoPy me deu muitos intervalos. Talvez 3 anos depois eles tenham relaxado suas restrições, então é ótimo saber!
Hamman Samuel
5

Passei cerca de 30 minutos tentando encontrar um exemplo de código de como fazer isso em Javascript. Não consegui encontrar uma resposta rápida e clara para a pergunta que você postou. Então ... eu fiz o meu. Espero que as pessoas possam usar isso sem ter que procurar na API ou olhar para o código que não têm idéia de como ler. Ha se nada mais eu posso referenciar este post para o meu próprio material .. Boa pergunta e obrigado pelo fórum de discussão!

Isso está utilizando a API do 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: '/' }); 
                }
        });
    }
}
Kai Husen
fonte
5

Sei que essa pergunta é realmente antiga, mas estou trabalhando no mesmo problema e encontrei um pacote extremamente eficiente e conveniente reverse_geocoder, criado por Ajay Thampi. O código está disponível aqui . Ele se baseou em uma implementação paralela de árvores KD, que é extremamente eficiente para grandes quantidades de pontos (levei alguns segundos para obter 100.000 pontos.

É baseado neste banco de dados, já destacado por @turgos.

Se sua tarefa é encontrar rapidamente o país e a cidade de uma lista de coordenadas, essa é uma ótima ferramenta.

Giorgio Balestrieri
fonte
3

Realmente depende de quais restrições de tecnologia você possui.

Uma maneira é ter um banco de dados espacial com o esboço dos países e cidades em que você está interessado. Por esboço, quero dizer que países e cidades são armazenados como o polígono do tipo espacial. Seu conjunto de coordenadas pode ser convertido no ponto do tipo espacial e consultado nos polígonos para obter o nome do país / cidade onde o ponto está localizado.

Aqui estão alguns dos bancos de dados compatíveis com o tipo espacial: SQL server 2008 , MySQL , postGIS - uma extensão do postgreSQL e Oracle .

Se você deseja usar um serviço em vez de ter seu próprio banco de dados, use o GeoPlanet do Yahoo . Para a abordagem de serviço, consulte esta resposta em gis.stackexchange.com , que cobre a disponibilidade de serviços para resolver seu problema.

steenhulthin
fonte
1

Você pode usar a API de geocodificação do Google

Abaixo está a função php que retorna Endereço, Cidade, Estado e País

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;
}
Nishad Up
fonte
se eu desejar apenas o nível_area administrativo_3 ou a localidade (se o nível_area administrativo_3 não estiver disponível), qual devo modificar? novo para php ..
agosto
1

Loc2country é uma ferramenta baseada em Golang que retorna o código ISO alfa-3 do país para determinadas coordenadas de localização (lat / lon). Responde em microssegundos. Ele usa uma geohash para o mapa do país.

Os dados do geohash são gerados usando o georaptor .

Usamos geohash no nível 6 para esta ferramenta, ou seja, caixas de tamanho 1,2 km x 600 m.

Ashwin Nair
fonte
0

Por favor, verifique a resposta abaixo. Funciona para mim

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;
}
Jain Summved
fonte
0

Se você estiver usando a API do Google Places, é assim que você pode obter o país e a cidade do objeto de lugar usando 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;
  }
}
vedo27
fonte