Получите название города с помощью геолокации


145

Мне удалось получить широту и долготу пользователя с помощью геолокации на основе 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;
}

Я хочу отобразить название города, кажется, единственный способ получить его - использовать API обратной геолокации. Я прочитал документацию Google по обратной геолокации, но не знаю, как получить результат на моем сайте.

Я не знаю, как это использовать: "http://maps.googleapis.com/maps/api/geocode/json?latlng='+lat+','+long+'&sensor=true"для отображения названия города на странице.

Как я могу этого добиться?


4
Если вы не собираетесь использовать карты, вы ЗНАЕТЕ, что это противоречит TOS Google, верно? Пункт 10.4 здесь developers.google.com/maps/terms Запрещается использование Контента без карты Google. Если Документация API Карт явно не разрешает вам это делать, вы не будете использовать Контент в Реализации API Карт без соответствующей карты Google. Например, вы можете отображать изображения Street View без соответствующей карты Google, потому что Документация API Карт прямо разрешает такое использование.
PirateApp

5
Да, @PirateApp подытожил. Там могут быть лучшие услуги. Я уже работал со SmartyStreets раньше и знаю, что у них гораздо более открытые Условия обслуживания. Однако большинство сервисов не выполняет обратное геокодирование. Я знаю, что у Texas A&M есть бесплатный сервис, но у них есть предупреждение TOS, что вы не можете собирать данные о других людях, и у них раньше были проблемы с безотказной работой и точностью.
Джозеф Хансен

Ответы:


204

Вы бы сделали что-то подобное с помощью Google API.

Обратите внимание, что вы должны включить библиотеку карт Google, чтобы это работало. Геокодер Google возвращает множество компонентов адреса, поэтому вы должны предположить, какой из них будет иметь город.

Обычно вы ищете "administrator_area_level_1", но иногда вам нужен город.

В любом случае - более подробную информацию о типах ответов Google можно найти здесь и здесь .

Ниже приведен код, который должен помочь:

<!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> 

3
Не верно для уровня админки 1, иногда название города отсутствует. - {"long_name" => "Сан-Франциско", "types" => ["administrator_area_level_2", "политический"], "short_name" => "Сан-Франциско"}, {"long_name" => "Калифорния", "типы "=> [" administrator_area_level_1 "," политический "]," short_name "=>" CA "}, {" long_name "=>" Соединенные Штаты "," types "=> [" страна "," политический "]," short_name "=>" US "}
Мин Цай,

5
Для V3 строку {'latlng': latlng} следует изменить на 'location', как в ... geocode ({'location': latlng}). В этом примере я почти достиг цели, но строка 'latlng' больше не действует в новых API. См .: developers.google.com/maps/documentation/javascript/… для уточнения деталей.
binarygiant 04

@Michal, как мы можем найти только название страны или код страны вместо полного адреса?
Аджай

1
@ajay в тесте оператора if для "страны" и переменная города теперь будет возвращать данные о стране. Если переименовать его в country = results [0] .address_components [i], вы можете получить доступ к данным по country.long_name и country.short_name
Michal

Есть ли способ сузить это число до городов в пределах провинции или просто проверить, находится ли местоположение из определенной провинции, и перенаправляется ли пользователь на определенную веб-страницу?
SorryEh 06

57

$.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>

Для использования геолокации html5 требуется разрешение пользователя. Если вы этого не хотите, выберите внешний локатор, например https://geolocation-db.com. Поддерживается IPv6. Никаких ограничений и неограниченных запросов.

пример

Для примера чистого javascript, без использования jQuery, ознакомьтесь с этим ответом.


Большое спасибо за это сокровище @OP. Потратив 1 час на SO, это первая ссылка (geolocation-db.com), которую я нашел, где служба поддерживает неограниченное количество бесплатных обращений к API в день.
siwalikm

53

Другой подход к этому - использование моей службы http://ipinfo.io , которая возвращает название города, региона и страны на основе текущего IP-адреса пользователя. Вот простой пример:

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

Вот более подробный пример JSFiddle, который также распечатывает полную информацию об ответе, чтобы вы могли видеть все доступные сведения: http://jsfiddle.net/zK5FN/2/


24
Хотя не так точно.
Салман фон Аббас

4
Не удалось определить город и даже тригион с IP крупного российского провайдера: (
Джехи

2
Лол ... это дает мой внутренний сетевой IP (192.168 ...)
майор-манн

Могу ли я сделать это из браузера устройства (карманного компьютера)?
Arti

Не кажется надежным. Я использую ноутбук и мобильный телефон прямо сейчас. Города, показанные на обоих устройствах через ipinfo.io, находятся на расстоянии 530 километров друг от друга!
Ашиш Гоял

18

Вы можете получить название города, страны, улицы и другие геоданные с помощью API геокодирования Google Maps.

<!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>

и отображать эти данные на странице с помощью 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>

16

Вот обновленная рабочая версия для меня, которая получит город / город. Похоже, что некоторые поля изменены в ответе json. Ссылаясь на предыдущие ответы на эти вопросы. (Спасибо Михалу и еще одна ссылка: Ссылка

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

11

geolocator.js может это сделать. (Я автор).

Получение названия города (ограниченный адрес)

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

Получение полной адресной информации

Пример ниже сначала попробует HTML5 Geolocation API, чтобы получить точные координаты. В случае неудачи или отклонения он вернется к поиску Geo-IP. Как только он получит координаты, он выполнит обратное геокодирование координат в адрес.

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

При этом используются внутренние API Google (для поиска адресов). Итак, перед этим вызовом вы должны настроить геолокатор с вашим ключом Google API.

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

Геолокатор поддерживает геолокацию (через HTML5 или поиск IP), геокодирование, поиск адресов (обратное геокодирование), расстояние и продолжительность, информацию о часовом поясе и многие другие функции ...


8

После некоторого поиска и объединения нескольких разных решений вместе с моими собственными вещами я придумал эту функцию:

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

4

Вы можете использовать https://ip-api.io/, чтобы получить название города. Он поддерживает IPv6.

В качестве бонуса он позволяет проверить, является ли IP-адрес узлом tor, публичным прокси или спамером.

Код 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);
                 });
        });
    });

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>

Вывод 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
    }
}

3

Как отметил @PirateApp в своем комментарии, использование API Карт по вашему намерению явно противоречит лицензированию Google Maps API.

У вас есть несколько альтернатив, включая загрузку базы данных Geoip и ее локальный запрос или использование сторонней службы API, такой как моя служба ipdata.co .

ipdata предоставляет данные о геолокации, организации, валюте, часовом поясе, коде вызова, флаге и статусе Tor Exit Node с любого адреса IPv4 или IPv6.

И масштабируется с помощью 10 глобальных конечных точек, каждая из которых может обрабатывать> 10 000 запросов в секунду!

В этом ответе используется «тестовый» API-ключ, который очень ограничен и предназначен только для тестирования нескольких вызовов. Зарегистрируйтесь для получения собственного бесплатного ключа API и получайте до 1500 запросов на разработку ежедневно.

$.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>

Скрипка; https://jsfiddle.net/ipdata/6wtf0q4g/922/


1

Вот еще одна попытка ... Добавление большего к принятому ответу, возможно, более исчерпывающему ... конечно, switch -case сделает его элегантным.

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

0

Вот простая функция, которую вы можете использовать для его получения. Я использовал axios для запроса API, но вы можете использовать все, что угодно.

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