Obter nome da cidade usando geolocalização

140

Consegui obter a latitude e longitude do usuário usando a geolocalização baseada em 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;
}

Quero exibir o nome da cidade, parece que a única maneira de obtê-lo é usar uma API de geolocalização reversa. Li a documentação do Google para geolocalização reversa, mas não sei como obter a saída no meu site.

Não sei como usar: "http://maps.googleapis.com/maps/api/geocode/json?latlng='+lat+','+long+'&sensor=true"para exibir o nome da cidade na página.

Como posso conseguir isso?

lisovaccaro
fonte
4
Se você não vai usar mapas, SABE que isso é contra os Termos de Serviço do Google, certo? Ponto 10.4 aqui developers.google.com/maps/terms Não é possível usar conteúdo sem um mapa do Google. A menos que a documentação das APIs do Google Maps permita expressamente, você não usará o conteúdo em uma implementação da API do Google Maps sem um mapa do Google correspondente. Por exemplo, você pode exibir imagens do Street View sem um mapa do Google correspondente, porque a documentação das APIs do Google Maps permite expressamente esse uso.
PirateApp 20/08/16
5
Sim, o @PirateApp tem um bom argumento. Pode haver melhores serviços por aí. Já trabalhei com o SmartyStreets e sei que eles têm muito mais Termos de Serviço abertos. A maioria dos serviços não faz geocodificação reversa, no entanto. Eu sei que o Texas A&M tem um serviço gratuito, mas eles têm um aviso do TOS de que você não pode coletar dados de outras pessoas e que eles já tiveram problemas de tempo de atividade e precisão.
Joseph Hansen

Respostas:

201

Você faria algo assim usando a API do Google.

Observe que você deve incluir a biblioteca do Google Maps para que isso funcione. O geocoder do Google retorna muitos componentes de endereço, portanto, você deve adivinhar qual será a cidade.

"administrativo_area_level_1" geralmente é o que você procura, mas às vezes a localidade é a cidade que você procura.

De qualquer forma - mais detalhes sobre os tipos de resposta do Google podem ser encontrados aqui e aqui .

Abaixo está o código que deve executar o truque:

<!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> 
Michal
fonte
3
Não é verdade para o nível 1 da área administrativa, às vezes o nome da cidade não está lá. - {"long_name" => "São Francisco", "tipos" => ["administrativo_area_level_2", "político"], "short_name" => "São Francisco"}, {"long_name" => "Califórnia", "tipos "=> [" administrativo_area_level_1 "," político "]," short_name "=>" CA "}, {" long_name "=>" Estados Unidos "," tipos "=> [" país "," político "]," short_name "=>" US "}
Ming Tsai
5
Para a V3, a string {'latlng': latlng} deve ser alterada para 'location', como em ... geocode ({'location': latlng}). Este exemplo me levou quase até lá, mas a string 'latlng' não parece mais ser válida em novas APIs. Veja: developers.google.com/maps/documentation/javascript/… para detalhes.
binarygiant
@Michal Como podemos encontrar apenas o nome ou o código do país em vez do endereço completo?
ajay
1
@ajay no teste da instrução if para "country" e a variável city agora retornará dados do país. Se re nome-it country = resultados [0] .address_components [i] você pode acessar os dados por country.long_name e country.short_name
Michal
Existe uma maneira de restringir isso a cidades dentro de uma província ou apenas para verificar se o local é de uma província específica e se o usuário é redirecionado para uma página da web específica?
SorryEh
52

Outra abordagem é usar meu serviço, http://ipinfo.io , que retorna o nome da cidade, região e país com base no endereço IP atual do usuário. Aqui está um exemplo simples:

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

Aqui está um exemplo mais detalhado do JSFiddle que também imprime as informações completas da resposta, para que você possa ver todos os detalhes disponíveis: http://jsfiddle.net/zK5FN/2/

Ben Dowling
fonte
23
Não é tão preciso.
Salman von Abbas
4
Não foi possível detectar a cidade e nem o trgion do IP de um grande provedor russo: (
Jehy
2
Lol ... isso dá meu ip interno de rede (192.168 ...)
major-mann
Posso fazer isso em um navegador de dispositivo (portátil)?
Arti
Não parece confiável. Estou usando um laptop e um celular agora. As cidades mostradas nos dois dispositivos através do ipinfo.io estão separadas por 530 quilômetros!
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>

O uso da geolocalização html5 requer permissão do usuário. Caso você não queira isso, procure um localizador externo como https://geolocation-db.com. IPv6 é suportado. Sem restrições e solicitações ilimitadas permitidas.

Exemplo

Para um exemplo puro de javascript, sem usar o jQuery, confira esta resposta.

Kurt Van den Branden
fonte
17

Você pode obter o nome da cidade, país, nome da rua e outros dados geográficos usando a API de geocodificação do 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>

e para exibir esses dados na página usando 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>
Mikhail
fonte
15

Aqui está a versão de trabalho atualizada para mim, que receberá Cidade / Cidade. Parece que alguns campos foram modificados na resposta json. Referindo respostas anteriores para essas perguntas. (Graças a Michal e mais uma referência: 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
fonte
10

geolocator.js pode fazer isso. (Eu sou o autor).

Obtendo o nome da cidade (endereço limitado)

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

Obtendo informações completas sobre o endereço

O exemplo abaixo tentará primeiro a API de localização geográfica em HTML5 para obter as coordenadas exatas. Se falhar ou rejeitar, ele retornará à pesquisa de Geo-IP. Depois de obter as coordenadas, o código geográfico será revertido para um endereço.

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

Isso usa as APIs do Google internamente (para pesquisa de endereços). Portanto, antes desta chamada, você deve configurar o geolocator com sua chave da API do Google.

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

O Geolocator suporta localização geográfica (via pesquisas em HTML5 ou IP), geocodificação, pesquisas de endereço (geocodificação reversa), distância e duração, informações de fuso horário e muito mais recursos ...

Onur Yıldırım
fonte
6

Depois de pesquisar e montar algumas soluções diferentes, além das minhas próprias coisas, criei esta função:

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
fonte
3

Você pode usar https://ip-api.io/ para obter o nome da cidade. Ele suporta IPv6.

Como bônus, permite verificar se o endereço IP é um nó tor, proxy público ou spammer.

Código 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);
                 });
        });
    });

Código 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>

Saída 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
fonte
2

Como o @PirateApp mencionado em seu comentário, é explicitamente contra o Licenciamento da API do Google Maps usar a API do Google como você deseja.

Você tem várias alternativas, incluindo baixar um banco de dados Geoip e consultá-lo localmente ou usar um serviço de API de terceiros, como meu serviço ipdata.co .

O ipdata fornece os dados de localização geográfica, organização, moeda, fuso horário, código de chamada, sinalizador e status do Tor Exit Node de qualquer endereço IPv4 ou IPv6.

E é escalável com 10 pontos de extremidade globais, cada um capaz de lidar com> 10.000 solicitações por segundo!

Esta resposta usa uma chave de API 'teste' muito limitada e destinada apenas ao teste de algumas chamadas. Inscreva-se em sua própria chave de API gratuita e receba até 1500 solicitações diárias para desenvolvimento.

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

O violino; https://jsfiddle.net/ipdata/6wtf0q4g/922/

Jonathan
fonte
1

Aqui está outro exemplo disso. Adicionando mais à resposta aceita, possivelmente mais abrangente .. é claro que switch -case fará com que pareça elegante.

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

Aqui está uma função fácil que você pode usar para obtê-la. Usei axios para fazer a solicitação da API, mas você pode usar qualquer outra coisa.

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
fonte