Uzyskaj nazwę miasta za pomocą geolokalizacji

140

Udało mi się uzyskać szerokość i długość geograficzną użytkownika za pomocą geolokalizacji opartej na HTML.

//Check if browser supports W3C Geolocation API
if (navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(successFunction, errorFunction);
} 
//Get latitude and longitude;
function successFunction(position) {
    var lat = position.coords.latitude;
    var long = position.coords.longitude;
}

Chcę wyświetlić nazwę miasta, wydaje się, że jedynym sposobem, aby to uzyskać, jest użycie interfejsu API odwrotnej geolokalizacji. Czytałem dokumentację Google dotyczącą odwrotnej geolokalizacji, ale nie wiem, jak uzyskać dane wyjściowe w mojej witrynie.

Nie wiem, jak to zrobić: "http://maps.googleapis.com/maps/api/geocode/json?latlng='+lat+','+long+'&sensor=true"aby wyświetlić nazwę miasta na stronie.

Jak mogę to osiągnąć?

lisovaccaro
źródło
4
Jeśli nie zamierzasz używać map, WIESZ, że jest to sprzeczne z warunkami korzystania z usług Google, prawda? Punkt 10.4 tutaj developers.google.com/maps/terms Zakaz korzystania z Treści bez mapy Google. O ile Dokumentacja Maps APIs wyraźnie na to nie zezwala, nie będziecie Państwo używać Treści w Implementacji Maps API bez odpowiedniej mapy Google. Na przykład możesz wyświetlać zdjęcia Street View bez odpowiedniej mapy Google, ponieważ Dokumentacja interfejsów API Map wyraźnie zezwala na takie użycie.
PirateApp
5
Tak, @PirateApp ma rację. Tam mogą być lepsze usługi. Pracowałem wcześniej ze SmartyStreets i wiem, że mają one znacznie bardziej otwarte Warunki korzystania z usługi. Większość usług nie wykonuje jednak odwrotnego geokodowania. Wiem, że Texas A&M ma bezpłatną usługę, ale mają ostrzeżenie TOS, że nie można zbierać danych o innych osobach, a wcześniej mieli problemy z czasem pracy i dokładnością.
Joseph Hansen

Odpowiedzi:

201

Zrobiłbyś coś takiego za pomocą Google API.

Pamiętaj, że aby to działało, musisz dołączyć bibliotekę map Google. Geocoder Google zwraca wiele składników adresu, więc musisz zgadnąć, który z nich będzie miał miasto.

„Administrative_area_level_1” jest zwykle tym, czego szukasz, ale czasami miejscowość to miasto, którego szukasz.

Tak czy inaczej - więcej szczegółów na temat typów odpowiedzi Google można znaleźć tutaj i tutaj .

Poniżej kod, który powinien załatwić sprawę:

<!DOCTYPE html> 
<html> 
<head> 
<meta name="viewport" content="initial-scale=1.0, user-scalable=no"/> 
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/> 
<title>Reverse Geocoding</title> 

<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?sensor=false"></script> 
<script type="text/javascript"> 
  var geocoder;

  if (navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(successFunction, errorFunction);
} 
//Get the latitude and the longitude;
function successFunction(position) {
    var lat = position.coords.latitude;
    var lng = position.coords.longitude;
    codeLatLng(lat, lng)
}

function errorFunction(){
    alert("Geocoder failed");
}

  function initialize() {
    geocoder = new google.maps.Geocoder();



  }

  function codeLatLng(lat, lng) {

    var latlng = new google.maps.LatLng(lat, lng);
    geocoder.geocode({'latLng': latlng}, function(results, status) {
      if (status == google.maps.GeocoderStatus.OK) {
      console.log(results)
        if (results[1]) {
         //formatted address
         alert(results[0].formatted_address)
        //find country name
             for (var i=0; i<results[0].address_components.length; i++) {
            for (var b=0;b<results[0].address_components[i].types.length;b++) {

            //there are different types that might hold a city admin_area_lvl_1 usually does in come cases looking for sublocality type will be more appropriate
                if (results[0].address_components[i].types[b] == "administrative_area_level_1") {
                    //this is the object you are looking for
                    city= results[0].address_components[i];
                    break;
                }
            }
        }
        //city data
        alert(city.short_name + " " + city.long_name)


        } else {
          alert("No results found");
        }
      } else {
        alert("Geocoder failed due to: " + status);
      }
    });
  }
</script> 
</head> 
<body onload="initialize()"> 

</body> 
</html> 
Michał
źródło
3
Nie dotyczy obszaru administracyjnego poziomu 1, czasami nie ma tam nazwy miasta. - {"long_name" => "San Francisco", "types" => ["Administrative_area_level_2", "polityczne"], "short_name" => "San Francisco"}, {"long_name" => "Kalifornia", "typy "=> [" poziom_administracyjny_1 "," polityczny "]," short_name "=>" CA "}, {" long_name "=>" Stany Zjednoczone "," types "=> [" kraj "," polityczny "]," short_name "=>" US "}
Ming Tsai
5
W wersji 3 ciąg {'latlng': latlng} należy zmienić na 'lokalizacja', jak w ... geocode ({'location': latlng}). Ten przykład prawie mnie doprowadził, ale ciąg „latlng” nie wydaje się już być prawidłowy w nowszych plikach API. Szczegółowe informacje można znaleźć pod adresem: developers.google.com/maps/documentation/javascript/… .
binarygiant
@Michal jak możemy znaleźć tylko nazwę kraju lub kod kraju zamiast pełnego adresu?
ajay
1
@ajay w teście instrukcji if dla „kraju” i zmiennej miasta będą teraz zwracać dane o kraju. Jeśli zmienisz nazwę country = results [0] .address_components [i], możesz uzyskać dostęp do danych według country.long_name i country.short_name
Michał
Czy jest sposób, aby zawęzić to do miast w prowincji, czy po prostu sprawdzić, czy lokalizacja pochodzi z określonej prowincji i czy użytkownik jest przekierowywany na określoną stronę internetową?
Przepraszam, Eh,
52

Innym podejściem do tego jest użycie mojej usługi http://ipinfo.io , która zwraca nazwę miasta, regionu i kraju na podstawie aktualnego adresu IP użytkownika. Oto prosty przykład:

$.get("http://ipinfo.io", function(response) {
    console.log(response.city, response.country);
}, "jsonp");

Oto bardziej szczegółowy przykład JSFiddle, który również drukuje pełne informacje o odpowiedzi, dzięki czemu możesz zobaczyć wszystkie dostępne szczegóły: http://jsfiddle.net/zK5FN/2/

Ben Dowling
źródło
23
Jednak nie tak dokładne.
Salman von Abbas,
4
Nie można wykryć miasta, a nawet trgionu z adresu IP dużego rosyjskiego dostawcy: (
Jehy
2
Lol ... to daje mojej wewnętrznej sieci IP (192.168 ...)
major-mann
Czy mogę to zrobić za pomocą przeglądarki urządzenia (podręcznej)?
Arti
Nie wydaje się wiarygodne. W tej chwili używam laptopa i telefonu komórkowego. Miasta pokazane na obu urządzeniach za pośrednictwem ipinfo.io są oddalone od siebie o 530 kilometrów!
Ashish Goyal
52

$.ajax({
  url: "https://geolocation-db.com/jsonp",
  jsonpCallback: "callback",
  dataType: "jsonp",
  success: function(location) {
    $('#country').html(location.country_name);
    $('#state').html(location.state);
    $('#city').html(location.city);
    $('#latitude').html(location.latitude);
    $('#longitude').html(location.longitude);
    $('#ip').html(location.IPv4);
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>

<div>Country: <span id="country"></span></div>
  <div>State: <span id="state"></span></div>
    <div>City: <span id="city"></span></div>
      <div>Latitude: <span id="latitude"></span></div>
        <div>Longitude: <span id="longitude"></span></div>
          <div>IP: <span id="ip"></span></div>

Korzystanie z geolokalizacji html5 wymaga zgody użytkownika. Jeśli tego nie chcesz, przejdź do zewnętrznego lokalizatora, takiego jak https://geolocation-db.com IPv6 jest obsługiwany. Brak ograniczeń i nieograniczona liczba żądań.

Przykład

Aby zapoznać się z czystym przykładem JavaScript, bez użycia jQuery, sprawdź odpowiedź.

Kurt Van den Branden
źródło
17

Możesz uzyskać nazwę miasta, kraju, nazwę ulicy i inne dane geograficzne za pomocą Google Maps Geocoding API

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <script type="text/javascript" src="https://code.jquery.com/jquery-2.2.3.js"></script>
</head>
<body>
    <script type="text/javascript">
        navigator.geolocation.getCurrentPosition(success, error);

        function success(position) {
            console.log(position.coords.latitude)
            console.log(position.coords.longitude)

            var GEOCODING = 'https://maps.googleapis.com/maps/api/geocode/json?latlng=' + position.coords.latitude + '%2C' + position.coords.longitude + '&language=en';

            $.getJSON(GEOCODING).done(function(location) {
                console.log(location)
            })

        }

        function error(err) {
            console.log(err)
        }
    </script>
</body>
</html>

i wyświetlić te dane na stronie za pomocą jQuery

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <script type="text/javascript" src="https://code.jquery.com/jquery-2.2.3.js"></script>
</head>
<body>

    <p>Country: <span id="country"></span></p>
    <p>State: <span id="state"></span></p>
    <p>City: <span id="city"></span></p>
    <p>Address: <span id="address"></span></p>

    <p>Latitude: <span id="latitude"></span></p>
    <p>Longitude: <span id="longitude"></span></p>

    <script type="text/javascript">
        navigator.geolocation.getCurrentPosition(success, error);

        function success(position) {

            var GEOCODING = 'https://maps.googleapis.com/maps/api/geocode/json?latlng=' + position.coords.latitude + '%2C' + position.coords.longitude + '&language=en';

            $.getJSON(GEOCODING).done(function(location) {
                $('#country').html(location.results[0].address_components[5].long_name);
                $('#state').html(location.results[0].address_components[4].long_name);
                $('#city').html(location.results[0].address_components[2].long_name);
                $('#address').html(location.results[0].formatted_address);
                $('#latitude').html(position.coords.latitude);
                $('#longitude').html(position.coords.longitude);
            })

        }

        function error(err) {
            console.log(err)
        }
    </script>
</body>
</html>
Michaił
źródło
15

Oto zaktualizowana wersja robocza dla mnie, która otrzyma Miasto / Miasto, Wygląda na to, że niektóre pola są zmodyfikowane w odpowiedzi json. Nawiązując do poprzednich odpowiedzi na to pytanie. (Podziękowania dla Michała i jeszcze jednej referencji: Link

var geocoder;

if (navigator.geolocation) {
  navigator.geolocation.getCurrentPosition(successFunction, errorFunction);
}
// Get the latitude and the longitude;
function successFunction(position) {
  var lat = position.coords.latitude;
  var lng = position.coords.longitude;
  codeLatLng(lat, lng);
}

function errorFunction() {
  alert("Geocoder failed");
}

function initialize() {
  geocoder = new google.maps.Geocoder();

}

function codeLatLng(lat, lng) {
  var latlng = new google.maps.LatLng(lat, lng);
  geocoder.geocode({latLng: latlng}, function(results, status) {
    if (status == google.maps.GeocoderStatus.OK) {
      if (results[1]) {
        var arrAddress = results;
        console.log(results);
        $.each(arrAddress, function(i, address_component) {
          if (address_component.types[0] == "locality") {
            console.log("City: " + address_component.address_components[0].long_name);
            itemLocality = address_component.address_components[0].long_name;
          }
        });
      } else {
        alert("No results found");
      }
    } else {
      alert("Geocoder failed due to: " + status);
    }
  });
}
Pradeep
źródło
10

geolocator.js może to zrobić. (Jestem autorem).

Pobieranie nazwy miasta (ograniczony adres)

geolocator.locateByIP(options, function (err, location) {
    console.log(location.address.city);
});

Pobieranie pełnych informacji adresowych

Poniższy przykład najpierw spróbuje API geolokalizacji HTML5, aby uzyskać dokładne współrzędne. Jeśli się nie powiedzie lub zostanie odrzucone, powróci do wyszukiwania Geo-IP. Po uzyskaniu współrzędnych odwróci współrzędne geokodują do adresu.

var options = {
    enableHighAccuracy: true,
    fallbackToIP: true, // fallback to IP if Geolocation fails or rejected
    addressLookup: true
};
geolocator.locate(options, function (err, location) {
    console.log(location.address.city);
});

Wykorzystuje wewnętrznie interfejsy API Google (do wyszukiwania adresów). Dlatego przed tym wywołaniem należy skonfigurować geolokalizator za pomocą klucza Google API.

geolocator.config({
    language: "en",
    google: {
        version: "3",
        key: "YOUR-GOOGLE-API-KEY"
    }
});

Geolocator obsługuje geolokalizację (przez wyszukiwanie HTML5 lub IP), geokodowanie, wyszukiwanie adresów (odwrotne geokodowanie), odległość i czas trwania, informacje o strefie czasowej i wiele innych funkcji ...

Onur Yıldırım
źródło
6

Po kilku poszukiwaniach i złożeniu kilku różnych rozwiązań wraz z własnymi rzeczami, wymyśliłem tę funkcję:

function parse_place(place)
{
    var location = [];

    for (var ac = 0; ac < place.address_components.length; ac++)
    {
        var component = place.address_components[ac];

        switch(component.types[0])
        {
            case 'locality':
                location['city'] = component.long_name;
                break;
            case 'administrative_area_level_1':
                location['state'] = component.long_name;
                break;
            case 'country':
                location['country'] = component.long_name;
                break;
        }
    };

    return location;
}
Jafo
źródło
3

Możesz użyć https://ip-api.io/ aby uzyskać nazwę miasta. Obsługuje IPv6.

Jako bonus pozwala sprawdzić, czy adres IP jest węzłem tor, publicznym serwerem proxy lub spamerem.

Kod JavaScript:

$(document).ready(function () {
        $('#btnGetIpDetail').click(function () {
            if ($('#txtIP').val() == '') {
                alert('IP address is reqired');
                return false;
            }
            $.getJSON("http://ip-api.io/json/" + $('#txtIP').val(),
                 function (result) {
                     alert('City Name: ' + result.city)
                     console.log(result);
                 });
        });
    });

Kod HTML

<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<div>
    <input type="text" id="txtIP" />
    <button id="btnGetIpDetail">Get Location of IP</button>
</div>

Wyjście JSON

{
    "ip": "64.30.228.118",
    "country_code": "US",
    "country_name": "United States",
    "region_code": "FL",
    "region_name": "Florida",
    "city": "Fort Lauderdale",
    "zip_code": "33309",
    "time_zone": "America/New_York",
    "latitude": 26.1882,
    "longitude": -80.1711,
    "metro_code": 528,
    "suspicious_factors": {
        "is_proxy": false,
        "is_tor_node": false,
        "is_spam": false,
        "is_suspicious": false
    }
}
Vindhyachal Kumar
źródło
2

Jak wspomniał @PirateApp w swoim komentarzu, używanie interfejsu API Map zgodnie z zamierzeniami jest jednoznacznie sprzeczne z licencjonowaniem interfejsu API Map Google.

Masz wiele alternatyw, w tym pobieranie bazy danych Geoip i wysyłanie do niej zapytań lokalnie lub za pomocą usługi API innej firmy, takiej jak moja usługa ipdata.co .

ipdata podaje geolokalizację, organizację, walutę, strefę czasową, kod wywoławczy, flagę i dane o stanie węzła wyjściowego Tor z dowolnego adresu IPv4 lub IPv6.

I jest skalowalny dzięki 10 globalnym punktom końcowym, z których każdy może obsłużyć ponad 10 000 żądań na sekundę!

Ta odpowiedź używa klucza API „testowego”, który jest bardzo ograniczony i przeznaczony tylko do testowania kilku wywołań. Zarejestruj się, aby uzyskać własny darmowy klucz API i otrzymuj do 1500 żądań dziennie na rozwój.

$.get("https://api.ipdata.co?api-key=test", function(response) {
  $("#ip").html("IP: " + response.ip);
  $("#city").html(response.city + ", " + response.region);
  $("#response").html(JSON.stringify(response, null, 4));
}, "jsonp");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1><a href="https://ipdata.co">ipdata.co</a> - IP geolocation API</h1>

<div id="ip"></div>
<div id="city"></div>
<pre id="response"></pre>

Skrzypce; https://jsfiddle.net/ipdata/6wtf0q4g/922/

Jonathan
źródło
1

Oto kolejne podejście do tego… Dodanie więcej do zaakceptowanej odpowiedzi, być może bardziej kompleksowej… oczywiście przełączniki sprawią, że będzie wyglądać elegancko.

function parseGeoLocationResults(result) {
    const parsedResult = {}
    const {address_components} = result;

    for (var i = 0; i < address_components.length; i++) {
        for (var b = 0; b < address_components[i].types.length; b++) {
            if (address_components[i].types[b] == "street_number") {
                //this is the object you are looking for
                parsedResult.street_number = address_components[i].long_name;
                break;
            }
            else if (address_components[i].types[b] == "route") {
                //this is the object you are looking for
                parsedResult.street_name = address_components[i].long_name;
                break;
            }
            else if (address_components[i].types[b] == "sublocality_level_1") {
                //this is the object you are looking for
                parsedResult.sublocality_level_1 = address_components[i].long_name;
                break;
            }
            else if (address_components[i].types[b] == "sublocality_level_2") {
                //this is the object you are looking for
                parsedResult.sublocality_level_2 = address_components[i].long_name;
                break;
            }
            else if (address_components[i].types[b] == "sublocality_level_3") {
                //this is the object you are looking for
                parsedResult.sublocality_level_3 = address_components[i].long_name;
                break;
            }
            else if (address_components[i].types[b] == "neighborhood") {
                //this is the object you are looking for
                parsedResult.neighborhood = address_components[i].long_name;
                break;
            }
            else if (address_components[i].types[b] == "locality") {
                //this is the object you are looking for
                parsedResult.city = address_components[i].long_name;
                break;
            }
            else if (address_components[i].types[b] == "administrative_area_level_1") {
                //this is the object you are looking for
                parsedResult.state = address_components[i].long_name;
                break;
            }

            else if (address_components[i].types[b] == "postal_code") {
                //this is the object you are looking for
                parsedResult.zip = address_components[i].long_name;
                break;
            }
            else if (address_components[i].types[b] == "country") {
                //this is the object you are looking for
                parsedResult.country = address_components[i].long_name;
                break;
            }
        }
    }
    return parsedResult;
}
user3124360
źródło
0

Oto prosta funkcja, której możesz użyć, aby to uzyskać. Użyłem axios do wykonania żądania API, ale możesz użyć czegokolwiek innego.

async function getCountry(lat, long) {
  const { data: { results } } = await axios.get(`https://maps.googleapis.com/maps/api/geocode/json?latlng=${lat},${long}&key=${GOOGLE_API_KEY}`);
  const { address_components } = results[0];

  for (let i = 0; i < address_components.length; i++) {
    const { types, long_name } = address_components[i];

    if (types.indexOf("country") !== -1) return long_name;
  }
}
Kingsley Kbc Comics
źródło