Biorąc pod uwagę współrzędne szerokości i długości geograficznej, w jaki sposób możemy znaleźć miasto / kraj?

141

Na przykład, jeśli mamy taki zestaw współrzędnych

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

Jak możemy poznać miasto / kraj?

ming yeow
źródło
2
Prawdopodobnie będziesz potrzebować jakiejś bazy danych. Sam spróbuję zagrać z interfejsem API Map Google ... obsługuje szerokość / długość.
beatgammit
1
Zobacz także Pobierz kraj z szerokości geograficznej
hippietrail

Odpowiedzi:

96

Bezpłatny interfejs API Google Geocoding udostępnia tę usługę za pośrednictwem interfejsu API REST HTTP. Uwaga: API jest ograniczone pod względem użycia i stawki , ale możesz zapłacić za nieograniczony dostęp.

Wypróbuj ten link, aby zobaczyć przykład danych wyjściowych (to jest w formacie json, dane wyjściowe są również dostępne w formacie XML)

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

Kevin
źródło
akceptując to, ponieważ to jest ten, do którego ostatecznie zmierzam :) Odpowiedź Michaela jest z pewnością świetną opcją!
ming yeow
5
Odwrotne geokodowanie Google jest dozwolone tylko w połączeniu z Mapą Google. Jeśli szukasz rozwiązania, które nie ma takich ograniczeń (chociaż jest komercyjne i ma tylko miasta w USA), sprawdź: askgeo.com
James D
mapquest api to kolejna opcja, ponieważ w niektórych przypadkach nie ma ograniczeń szybkości i bardzo wysokich limitów szybkości dla różnych potrzeb geokodowania.
Tom
2
darmowe jest dyskusyjne, jest darmowe tylko w pewnych granicach.
Petah
@JamesD: zasady API stanowią, że jeśli wyświetlasz dane na mapie, to musi to być mapa Google, ale nie musisz ich wyświetlać na mapie (lub w ogóle).
user276648
173

Inna opcja:

  • Pobierz bazę danych miast ze strony http://download.geonames.org/export/dump/
  • Dodaj każde miasto jako szerokość / długość -> Mapowanie miasta do indeksu przestrzennego, takiego jak R-Tree (niektóre DB mają również tę funkcjonalność)
  • Użyj wyszukiwania najbliższego sąsiada, aby znaleźć najbliższe miasto dla dowolnego punktu

Zalety:

  • Nie zależy od dostępności serwera zewnętrznego
  • Bardzo szybki (z łatwością wykonuje tysiące wyszukiwań na sekundę)

Niedogodności:

  • Nieaktualne automatycznie
  • Wymaga dodatkowego kodu, jeśli chcesz rozróżnić przypadek, w którym najbliższe miasto jest oddalone o kilkadziesiąt kilometrów
  • Może dawać dziwne wyniki w pobliżu biegunów i międzynarodowej linii daty (choć i tak nie ma w tych miejscach żadnych miast
Michael Borgwardt
źródło
5
Daje również dziwne wyniki dla miast w miastach, na przykład niektóre lokalizacje w Rzymie mogą zwracać „Watykan” - w zależności od szerokości / długości określonej w bazie danych dla każdego z nich.
Noel Abrahams
1
Mają też REST api i wygląda całkiem przyzwoicie: api.geonames.org/ ...
jeudyx
8
Przykład byłby nieoceniony
Hack-R
GeoNames oferuje również darmową usługę internetową, która jest po prostu niesamowita!
mcont
W 2020 r.GeoNames.org wygląda na prawie nieaktywną, czy ktoś wie, czy jest w ogóle aktualna? Problem nigdzie nie wspominają o datach ostatniej aktualizacji na stronie.
joedotnot
45

Potrzebujesz geopy

pip install geopy

i wtedy:

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

print(location.address)

aby uzyskać więcej informacji:

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
źródło
2
Czy są jakieś ograniczenia? Wydaje się, że jest to najszybsze podejście. Czy może istnieć jakikolwiek powód, aby nie używać tego w stosunku do podejścia @ Michael?
Satys
1
cóż, wymaga serwisu zewnętrznego
maxbachmann
To świetne podejście, ale potrzebuję tylko hrabstw, więc muszę doprecyzować adres. Żałuję, że nie ma sposobu, który przywróciłby hrabstwa.
Fatemeh Asgarinejad
22

Alternatywą Open Source jest Nominatim z Open Street Map. Wszystko, co musisz zrobić, to ustawić zmienne w adresie URL i zwraca miasto / kraj tej lokalizacji. Sprawdź poniższy link, aby uzyskać oficjalną dokumentację: Nominatim

Rega
źródło
3
Zauważ, że polityka użytkowania Nominatim operations.osmfoundation.org/policies/nominatim określa maksymalną szybkość jednego żądania na sekundę, więc jest odpowiednia tylko dla zapytań ad-hoc.
Matthew Wise,
22

Szukałem podobnej funkcjonalności i zobaczyłem dane „ http://download.geonames.org/export/dump/ ” udostępnione we wcześniejszej odpowiedzi (dziękuję za udostępnienie, jest to doskonałe źródło) i wdrożyłem usługę opartą na na danych cities1000.txt.

Możesz zobaczyć, jak działa pod adresem http://scatter-otl.rhcloud.com/location?lat=36&long=-78.9 (uszkodzony link) Po prostu zmień szerokość i długość geograficzną dla swoich lokalizacji.

Jest wdrażany w OpenShift (platforma RedHat). Pierwsze połączenie po długim okresie bezczynności może trochę potrwać, ale zwykle wydajność jest zadowalająca. Zapraszam do korzystania z tej usługi w dowolny sposób ...

Możesz również znaleźć źródło projektu na https://github.com/turgos/Location .

turgos
źródło
To nie działa poprawnie. Jeśli nie może uzyskać miasta, wyszukuje najbliższe znane miasto. Oto przykład: scatter-otl.rhcloud.com/… Zamiast „Saint John” jest napisane „Basseterre” ...
smartmouse
1
To jest poprawne. algorytm przeszukuje najbliższe miasto dostępne w zbiorze danych. W przypadku powyższego serwera użyłem pliku „cities1000.txt”. Ma tylko największe miasta. Kod źródłowy jest dostępny pod adresem github.com/turgos/Location . Możesz rozpocząć własne z bardziej szczegółowymi danymi z „ download.geonames.org/export/dump ”.
turgos
Wydaje się, że dostępne są bardziej szczegółowe dane cities1000.txt. Czy mam rację?
smartmouse
8

Użyłem Geocodera , dobrej biblioteki Pythona, która obsługuje wielu dostawców, w tym Google, Geonames i OpenStreetMaps, aby wymienić tylko kilka . Próbowałem użyć biblioteki GeoPy i często pojawiają się limity czasu. Tworzenie własnego kodu dla GeoNames nie jest najlepszym sposobem wykorzystania Twojego czasu i możesz otrzymać niestabilny kod. Z mojego doświadczenia wynika, że ​​Geocoder jest bardzo prosty w użyciu i ma wystarczająco dobrą dokumentację . Poniżej znajduje się przykładowy kod do wyszukiwania miasta według szerokości i długości geograficznej lub wyszukiwania szerokości / długości geograficznej według nazwy miasta.

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
źródło
Dzięki za udostępnienie tego, ale nie działa to dla wszystkich współrzędnych. Czy liczba cyfr współrzędnych musi mieć określoną wielkość?
Fatemeh Asgarinejad
1
Wydaje mi się, że poprawnie wybrałem długość i szerokość geograficzną. Mam tysiące współrzędnych, z których przypadkowa współrzędna nie działa. Teraz jest dobrze. Zastosowałem inne podejście. Dzięki za twoją odpowiedź.
Fatemeh Asgarinejad
1
Witamy. Ciekawi Cię, jakie podejście zadziałało w Twoim przypadku? Jeśli to lepsze niż geocoder, sam też chciałbym spróbować!
Hamman Samuel
1
Użyłem tego: z geopy.geocoders import Nominatim geolocator = Nominatim () location = geolocator.reverse ("41.4721, -72.6311") print (location.address) Podaje cały adres, a następnie filtruję z niego powiat.
Fatemeh Asgarinejad
1
Dzięki, pracowałem z dużym zbiorem danych iw 2017 roku korzystanie z GeoPy przyniosło mi wiele limitów czasu. Może 3 lata później złagodzili swoje ograniczenia, więc dobrze wiedzieć!
Hamman Samuel
5

Spędziłem około 30 minut, próbując znaleźć przykładowy kod, jak to zrobić w JavaScript. Nie udało mi się znaleźć szybkiej i jasnej odpowiedzi na zadane przez Ciebie pytanie. Więc ... stworzyłem własne. Miejmy nadzieję, że ludzie mogą z tego korzystać bez konieczności zagłębiania się w API lub wpatrywania się w kod, którego nie mają pojęcia, jak czytać. Ha, jeśli nic więcej, mogę odnieść się do tego postu dla własnych rzeczy .. Miłe pytanie i dzięki za forum dyskusji!

To wykorzystuje 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: '/' }); 
                }
        });
    }
}
Kai Husen
źródło
5

Wiem, że to pytanie jest naprawdę stare, ale pracowałem nad tym samym problemem i znalazłem niezwykle wydajny i wygodny pakiet reverse_geocoder, zbudowany przez Ajaya Thampi. Kod jest dostępny tutaj . Opiera się na równoległej implementacji drzew KD, co jest niezwykle wydajne dla dużej liczby punktów (zajęło mi kilka sekund, aby uzyskać 100 000 punktów.

Opiera się na tej bazie danych, która została już wyróżniona przez @turgos.

Jeśli Twoim zadaniem jest szybkie znalezienie kraju i miasta z listy współrzędnych, jest to świetne narzędzie.

Giorgio Balestrieri
źródło
3

To naprawdę zależy od tego, jakie masz ograniczenia technologiczne.

Jednym ze sposobów jest posiadanie przestrzennej bazy danych zawierającej zarys krajów i miast, którymi jesteś zainteresowany. Przez zarys rozumiem, że kraje i miasta są przechowywane jako wielokąt typu przestrzennego. Twój zestaw współrzędnych może zostać przekonwertowany na punkt typu przestrzennego i porównany z wielokątami, aby uzyskać nazwę kraju / miasta, w którym znajduje się punkt.

Oto niektóre bazy danych obsługujące typ przestrzenny: SQL server 2008 , MySQL , postGIS - rozszerzenie postgreSQL i Oracle .

Jeśli chcesz skorzystać z usługi zamiast posiadania własnej bazy danych, możesz skorzystać z usługi GeoPlanet Yahoo . Jeśli chodzi o podejście do usług, możesz sprawdzić odpowiedź na gis.stackexchange.com , która obejmuje dostępność usług umożliwiających rozwiązanie problemu.

steenhulthin
źródło
1

Możesz użyć Google Geocoding API

Poniżej znajduje się funkcja php, która zwraca adres, miasto, stan i kraj

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
źródło
jeśli chcę tylko administracja_obszar_poziom_ 3 lub lokalność (jeśli administracyjna_obszar_poziom_ 3 nie jest dostępna), który z nich powinienem zmienić? nowy na php ..
sierpnia
1

Loc2country to narzędzie oparte na języku Golang, które zwraca kod kraju ISO alpha-3 dla podanych współrzędnych lokalizacji (szer. / Dł.). Odpowiada w mikrosekundach. Używa geohash do mapy kraju.

Dane geohash są generowane za pomocą georaptora .

Do tego narzędzia używamy geohaszu na poziomie 6, czyli skrzynek o wymiarach 1,2km x 600m.

Ashwin Nair
źródło
0

Sprawdź poniższą odpowiedź. Mi to pasuje

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;
}
Summved Jain
źródło
0

Jeśli korzystasz z interfejsu API Miejsc Google, możesz pobrać kraj i miasto z obiektu miejsca za pomocą 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
źródło