Dadas las coordenadas lat / long, ¿cómo podemos encontrar la ciudad / país?

141

Por ejemplo, si tenemos este conjunto de coordenadas

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

¿Cómo podemos averiguar la ciudad / país?

ming yeow
fuente
2
Probablemente necesitará una base de datos de algún tipo. Intentaría jugar con la API de Google Maps yo mismo ... es compatible con lat / long.
beatgammit
1
Ver también Obtener país de latitud longitud
hippietrail

Respuestas:

96

La API gratuita de Google Geocoding proporciona este servicio a través de una API HTTP REST. Tenga en cuenta que la API es de uso y tasa limitada , pero puede pagar por acceso ilimitado.

Pruebe este enlace para ver un ejemplo de la salida (esto está en json, la salida también está disponible en XML)

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

Kevin
fuente
aceptando esto porque este es el que termino :) La respuesta de Michael es, sin duda, una gran opción.
ming yeow
55
La geocodificación inversa de Google solo se permite junto con un mapa de Google. Si desea una solución que no tenga tales restricciones (aunque es comercial y solo tiene ciudades de EE. UU.), Consulte: askgeo.com
James D
mapquest api es otra opción aquí ya que no tiene límites de velocidad en algunos casos y límites de velocidad muy altos para diversas necesidades de geocodificación.
Tom
2
gratis es discutible, solo es gratis bajo ciertos límites.
Petah
@JamesD: las políticas de API establecen que si muestra los datos en un mapa, debe ser un mapa de Google, pero no tiene que mostrarlos en un mapa (o en absoluto).
user276648
173

Otra opción:

  • Descargue la base de datos de ciudades de http://download.geonames.org/export/dump/
  • Agregue cada ciudad como lat / long -> Mapeo de ciudades a un índice espacial como un R-Tree (algunos DB también tienen la funcionalidad)
  • Use la búsqueda de vecino más cercano para encontrar la ciudad más cercana para cualquier punto

Ventajas:

  • No depende de un servidor externo para estar disponible
  • Muy rápido (fácilmente realiza miles de búsquedas por segundo)

Desventajas

  • No actualizado automáticamente
  • Requiere un código adicional si desea distinguir el caso donde la ciudad más cercana está a docenas de millas de distancia
  • Puede dar resultados extraños cerca de los polos y la línea de fecha internacional (aunque de todos modos no hay ciudades en esos lugares)
Michael Borgwardt
fuente
55
También dará resultados extraños para ciudades dentro de ciudades, por ejemplo, ciertos lugares en Roma pueden devolver "Ciudad del Vaticano", dependiendo del lat / lon especificado en la base de datos para cada uno.
Noel Abrahams
1
También tienen una API REST y se ve bastante decente: api.geonames.org/…
jeudyx
8
Un ejemplo habría sido invaluable
Hack-R
GeoNames también ofrece un servicio web gratuito que es simplemente increíble.
mcont
En 2020, GeoNames.org parece bastante inactivo, ¿alguien sabe si es actual? El problema es que en ninguna parte mencionan las fechas de la última actualización en el sitio.
joedotnot
45

Necesitas geopy

pip install geopy

y entonces:

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

print(location.address)

para obtener más información:

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
fuente
2
¿Hay algún límite para este? Este parece ser el enfoque más rápido. ¿Podría haber alguna razón para no usar esto sobre el enfoque de @ Michael?
Sábados
1
bueno, requiere un servicio externo
maxbachmann
Es un gran enfoque, sin embargo, solo necesito los condados, así que necesito refinar la dirección. Desearía que hubiera una manera de devolver los condados.
Fatemeh Asgarinejad
22

Una alternativa de código abierto es Nominatim de Open Street Map. Todo lo que tiene que hacer es configurar las variables en una URL y devolverá la ciudad / país de esa ubicación. Consulte el siguiente enlace para obtener documentación oficial: Nominatim

Rega
fuente
3
Tenga en cuenta que la política de uso de Nominatim operations.osmfoundation.org/policies/nominatim establece una tasa máxima de una solicitud por segundo, por lo que solo es realmente adecuada para consultas ad-hoc.
Matthew Wise el
22

Estaba buscando una funcionalidad similar y vi los datos " http://download.geonames.org/export/dump/ " compartidos en una respuesta anterior (gracias por compartir, es una excelente fuente), e implementé un servicio basado en los datos de cities1000.txt.

Puedes verlo corriendo en http://scatter-otl.rhcloud.com/location?lat=36&long=-78.9 (enlace roto) Simplemente cambie la latitud y longitud de sus ubicaciones.

Se implementa en OpenShift (plataforma RedHat). La primera llamada después de un largo período de inactividad puede llevar algún tiempo, pero generalmente el rendimiento es satisfactorio. Siéntase libre de usar este servicio como desee ...

Además, puede encontrar la fuente del proyecto en https://github.com/turgos/Location .

turgos
fuente
No funciona adecuadamente. Si no puede obtener una ciudad, busca una ciudad conocida más cercana. He aquí un ejemplo: scatter-otl.rhcloud.com/... Dice "Basseterre" en lugar de "San Juan" ...
Smartmouse
1
Eso es correcto. el algoritmo busca la ciudad más cercana disponible en el conjunto de datos. Para el servidor desplegado anterior, utilicé "cities1000.txt". Tiene solo las principales ciudades. El código fuente está disponible en github.com/turgos/Location . Puede comenzar el suyo con datos más detallados de " download.geonames.org/export/dump ".
turgos
Parece que cities1000.txt es la información más detallada disponible. Estoy en lo cierto?
smartmouse
8

He usado Geocoder , una buena biblioteca de Python que admite múltiples proveedores, incluidos Google, Geonames y OpenStreetMaps, por mencionar solo algunos . Intenté usar la biblioteca GeoPy, y a menudo se agota el tiempo de espera. Desarrollar su propio código para GeoNames no es el mejor uso de su tiempo y puede terminar obteniendo código inestable. Geocoder es muy simple de usar en mi experiencia, y tiene suficiente documentación . A continuación se muestra un código de ejemplo para buscar ciudad por latitud y longitud, o encontrar latitud / longitud por nombre de ciudad.

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
fuente
Gracias por compartir esto, pero no funciona para todas las coordenadas. ¿El número de dígitos de las coordenadas debe tener un tamaño específico?
Fatemeh Asgarinejad
1
Creo que elegí la longitud y latitud correctamente. Tengo miles de coordenadas desde las cuales una coordenada aleatoria no funcionó. Está bien ahora. Usé otro enfoque. Gracias por su respuesta.
Fatemeh Asgarinejad
1
Bienvenidos. ¿Tienes curiosidad por saber qué enfoque funcionó para ti? Si es mejor que geocodereso, ¡también me gustaría probarlo!
Hamman Samuel
1
Utilicé esto: desde geopy.geocoders importamos Nominatim geolocator = Nominatim () location = geolocator.reverse ("41.4721, -72.6311") print (location.address) Da la dirección completa y luego filtro el condado.
Fatemeh Asgarinejad
1
Gracias, trabajé con un gran conjunto de datos y en 2017, usar GeoPy me dio muchos tiempos de espera. Quizás 3 años después hayan relajado sus restricciones, ¡eso es bueno saberlo!
Hamman Samuel
5

Pasé unos 30 minutos tratando de encontrar un ejemplo de código de cómo hacer esto en Javascript. No pude encontrar una respuesta rápida y clara a la pregunta que publicó. Entonces ... hice el mío. Esperemos que las personas puedan usar esto sin tener que buscar en la API o mirar el código que no tienen idea de cómo leer. Ja, si nada más, puedo hacer referencia a esta publicación para mis propias cosas. ¡Buena pregunta y gracias por el foro de discusión!

Esto está utilizando la API de 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
fuente
5

Sé que esta pregunta es muy antigua, pero he estado trabajando en el mismo problema y encontré un paquete extremadamente eficiente y conveniente reverse_geocoder, creado por Ajay Thampi. El código está disponible aquí. . Se basa en una implementación paralela de árboles KD que es extremadamente eficiente para grandes cantidades de puntos (me tomó unos segundos obtener 100,000 puntos.

Se basa en esta base de datos, ya resaltada por @turgos.

Si su tarea es encontrar rápidamente el país y la ciudad de una lista de coordenadas, esta es una gran herramienta.

Giorgio Balestrieri
fuente
3

Realmente depende de las restricciones tecnológicas que tenga.

Una forma es tener una base de datos espacial con el esquema de los países y ciudades que le interesan. Por esquema quiero decir que los países y ciudades se almacenan como el polígono de tipo espacial. Su conjunto de coordenadas se puede convertir al punto de tipo espacial y consultar con los polígonos para obtener el nombre del país / ciudad donde se encuentra el punto.

Estas son algunas de las bases de datos que admiten el tipo espacial: SQL Server 2008 , MySQL , postGIS , una extensión de postgreSQL y Oracle .

Si desea utilizar un servicio en lugar de tener su propia base de datos para esto, puede utilizar el GeoPlanet de Yahoo . Para el enfoque de servicio, puede consultar esta respuesta en gis.stackexchange.com , que cubre la disponibilidad de servicios para resolver su problema.

steenhulthin
fuente
1

Puedes usar la API de geocodificación de Google

A continuación se muestra la función php que devuelve Dirección, Ciudad, Estado y 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
fuente
si solo quiero el nivel de área administrativa 3 o la localidad (si el nivel de área administrativa 3 no está disponible), ¿cuál debo modificar? nuevo en php ..
August
1

Loc2country es una herramienta basada en Golang que devuelve el código de país ISO alfa-3 para determinadas coordenadas de ubicación (lat / lon). Responde en microsegundos. Utiliza un geohash al mapa del país.

Los datos de geohash se generan utilizando georaptor .

Utilizamos geohash en el nivel 6 para esta herramienta, es decir, cajas de tamaño 1.2km x 600m.

Ashwin Nair
fuente
0

Por favor, consulte la respuesta a continuación. Esto funciona para mi

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
fuente
0

Si está utilizando la API de Google Places, así es como puede obtener el país y la ciudad desde el 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
fuente