Saudações pessoal.
Como eu havia dito, vou tentar compartilhar com vocês mais algumas coisas sobre a utilização do GeoIP e do Google Maps.
Sem enrolação hoje, vamos às novidades.
Google Maps Javascript API V3
Em 05/2009, o Google lançou oficialmente a nova versão do Google Maps API, agora denominada Google Maps Javascript API V3 (versão 3). A grande diferença dessa versão para as anteriores, é que seu código foi melhor estruturado, para ser mais leve, mais eficiente, ser executado em dispositivos móveis com mais facilidade, além de ter incluído algumas novas funcionalidades, como o suporte ao padrão de geolocalização W3C, que, em resumo, permitem, com código javascript, acessar informações sobre localização em um dispositivo que possua GPS, como os smartphones de hoje em dia.
Mas, de modo prático, o que muda pra gente? Primeiro, que não precisamos mais daquela chatice de “chave de API” e, segundo, que a versão 2 “tem previsão de remoção”: ou seja, daqui a pouco, os códigos que utilizam a versão 2 do Google Maps API deixarão de funcionar. Mas, não se alarmem: como o próprio Google disse, a utilização da nova API é muito semelhante a anterior. Vejam esse tutorial completo sobre como começar a usar a versão 3 do Google Maps API, e vamos para o próximo item.
MaxMind GeoIP: novas APIs
Recentemente, recebi um comentário sobre uma dúvida na utilização da API para PHP do GeoIP. Mas eu realmente não lembrava de existir essa API quando criei o primeiro post sobre esse assunto. Realmente, utilizar aqueles pacotes PEAR é muito chato, além de ser mais complicado. Diante disso, fui até o site da MaxMind, na parte de APIs, e verifique que realmente existem várias APIs novinhas, e mais fáceis de ser utilizadas. Então, vou tentar mostrar aqui duas delas: a API para PHP puro, e a API para JavaScript.
GeoIP PHP API
Existem três maneiras de se usar o GeoIP utilizando o PHP como base. Uma, a gente já mostrou no post anterior, que é utilizando o pacote PEAR NetGeoIP. Outra maneira é utilizando um “mod” pro Apache, o mod_geoip. A terceira maneira é utilizando PHP puro, como o próprio site chama.
Existem duas diferenças básicas entre usar uma ou outra abordagem: a facilidade de uso e o desempenho, sendo que utilizando o PHP puro é o jeito mais fácil e rápido de implementar uma solução GeoIP, enquanto utilizar o mod_geoip é a maneira mais trabalhosa, mas que gera o resultando mais eficiente. Neste post, iremos usar o PHP puro.
Como vimos antes, a primeira coisa a se fazer é baixar a base de dados e colocá-la no seu servidor web. Neste caso, estamos utilizando a base de dados gratuita GeoLite City, que contém informações a nível de cidades. Após terminar de baixar, basta descompactar e fazer o upload para algum diretório do seu servidor web (veja lá no final desse post como fazer isso de uma maneira bem mais prática). No meu caso, utilizei o diretório /home/interpossi/geoip/
, dessa forma, toda vez que eu precisar do base de dados, basta eu informar o caminho /home/interpossi/geoip/GeoLiteCity.dat
. Você pode utilizar qualquer diretório, desde que lembre dele depois. 😛 Um dica é não criar esse diretório dentro de /public_html
, para não torná-lo público. Duvido que alguém irá querer acessar a base dessa maneira, mas…
Agora, é necessário baixar os arquivos da API. Para o nosso exemplo, iremos precisar apenas dos seguintes arquivos:
Agora é só fazer nosso arquivo de teste, que, devido a minha suprema criatividade, chamei de teste.php
. Veja como ficou o código:
<?php include("geoipcity.inc"); include("geoipregionvars.php"); //base de dados $base = geoip_open("/home/interpos/geoip/GeoLiteCity.dat",GEOIP_STANDARD); //pega um registro de localizacao baseado no IP do cliente (REMOTE_ADDR) $localizacao = geoip_record_by_addr($base,$_SERVER["REMOTE_ADDR"]); //fecha o arquivo (pra economizar memoria) geoip_close($base); //imprime na tela as informacoes obtidas ?> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <style type="text/css"> table { padding: 3px; } th { border: 2px outset #C0C0C0; padding: 3px; text-align: right;} td { border: 2px outset #C0C0C0; padding: 3px; text-align: left;} </style> </head> <body> <h1>Seu IP sugere que esta seja sua localização:</h1> <? echo "<table><tr>"; echo "<th>Codigo do Continente: </th><td>" . $localizacao->continent_code . "</td></tr><tr>"; echo "<th>Codigo do pais: </th><td>" . $localizacao->country_code . "</td></tr><tr>"; echo "<th>Codigo do pais com 3 letras: </th><td>" . $localizacao->country_code3 . "</td></tr><tr>"; echo "<th>Nome do pais: </th><td>" . $localizacao->country_name . "</td></tr><tr>"; echo "<th>Codigo do estado: </th><td>" . $localizacao->region . "</td></tr><tr>"; echo "<th>Nome do estado: </th><td>" . $GEOIP_REGION_NAME[$localizacao->country_code][$localizacao->region] . "</td></tr><tr>"; echo "<th>Nome da cidade: </th><td>" . $localizacao->city . "</td></tr><tr>"; echo "<th>Latitude: </th><td>" . $localizacao->latitude . "</td></tr><tr>"; echo "<th>Longitude: </th><td>" . $localizacao->longitude . "</td></tr>"; echo "</table>"; ?> <h2><a href="#">Retornar para o artigo</a></h2> </body> </html>
Para utilizarmos essa nova abordagem com o Google Maps é muito simples, basta usar os atributos “latitude e longitude” no código JavaScript do mapa. Vejam o código-fonte. Ele fala por si só (assim espero. Qualquer dúvida, postem comentários…).
<?php include("geoipcity.inc"); include("geoipregionvars.php"); //base de dados $base = geoip_open("/home/interpos/geoip/GeoLiteCity.dat",GEOIP_STANDARD); //pega um registro de localizacao baseado no IP do cliente (REMOTE_ADDR) $localizacao = geoip_record_by_addr($base,$_SERVER["REMOTE_ADDR"]); //fecha o arquivo (mas os dados continuam em $localizacao geoip_close($base); ?> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <!-- tamanho do viewport: mais utilizado em dispositivos moveis --> <meta name="viewport" content="initial-scale=1.0, user-scalable=no" /> <style type="text/css"> #map_canvas{ width:640px; height:480px; margin: 10px; border: 1px solid black; } </style> <!-- sensor=false : indicado para dizer se o dispositivo possui ou nao sensor GPS --> <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script> <script type="text/javascript"> function initialize() { var latlng = new google.maps.LatLng(<? echo $localizacao->latitude; ?>, <? echo $localizacao->longitude; ?>); var options = { zoom: 6, center: latlng, mapTypeId: google.maps.MapTypeId.ROADMAP }; var map = new google.maps.Map(document.getElementById("map_canvas"), options); var marker = new google.maps.Marker({ position: latlng, map: map, title:"Seu IP sugere que você esteja por aqui" }); } </script> </head> <body onload="initialize()"> <h1>Seu IP sugere que esta seja sua localização:</h1> <div id="map_canvas"></div> <h2><a href="#">Retornar para o artigo</a></h2> </body> </html>
Tranquilinho né? Vamos ao próximo, e sem dúvida, mais interessante.
GeoIP JavaScript API
Um outra API que encontrei no site da MaxMind foi essa: bibliotecas GeoIP para JavaScript.
Eu, particularmente, me dou muito bem com o JavaScript. Então, a ideia de poder usar o GeoIP direto no código JS já me pareceu boa. Além disso, o uso da API do JavaScript permite a você utilizar a base de dados “paga” da MaxMind. Sim! Teoricamente, você teria resultados mais precisos. A única imposição deles é que você deixe um link pro site da MaxMind na página em que utilizar o JS deles (ou pague a licensa de 250 dólares por ano). (Mais ainda, com um pouco de criatividade, praticamente qualquer linguagem que possa fazer uma requisição HTTP consegue ter acesso ao GeoIP, bastando pra isso, recuperar as informações desse link, e claro, exibindo o “linkzinho” da MaxMind);
Então, como fazemos pra usar? Simples, no seu “código” html (html é código? não né.. linguagem de marcação) inclua o script deles:
<script language="JavaScript" src="http://j.maxmind.com/app/geoip.js"></script>
E depois é só chamar os métodos, como o geoip_latitude()
e geoip_longitude()
. Veja um código de exemplo:
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <!-- tamanho do viewport: mais utilizado em dispositivos moveis --> <meta name="viewport" content="initial-scale=1.0, user-scalable=no" /> <style type="text/css"> #map_canvas{ width:640px; height:480px; margin: 10px; border: 1px solid black; } </style> <!-- funcoes (se eh que podem ser chamadas assim) geoip --> <script language="JavaScript" src="http://j.maxmind.com/app/geoip.js"></script> <!-- sensor=false : indicado para dizer se o dispositivo possui ou nao sensor GPS --> <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script> <script type="text/javascript"> function initialize() { var latlng = new google.maps.LatLng(geoip_latitude(), geoip_longitude()); var options = { zoom: 9, center: latlng, mapTypeId: google.maps.MapTypeId.ROADMAP }; var map = new google.maps.Map(document.getElementById("map_canvas"), options); var marker = new google.maps.Marker({ position: latlng, map: map, title:"Seu IP sugere que você esteja em "+geoip_city()+" - "+geoip_region_name() }); } </script> </head> <body onload="initialize()"> <h1>Seu IP sugere que esta seja sua localização:</h1> <div id="map_canvas"></div> <h2><a href="#">Retornar para o artigo</a></h2> </body> </html>
Notem que as únicas coisas a se fazer é incluir a biblioteca JS e chamar suas duas funções geoip_latitude()
e geoip_longitude()
, enviando seus resultados diretamente pro código do Google Maps.
Comparem a localização estimada da versão PHP com a versão JS: qual foi mais preciso pra vocês?
Dica bonus: baixar e atualizar a base de dados GeoIP
Essa dica é simplesmente um script PHP para baixar a base de dados diretamente para o servidor, evitando que você tenha que baixar para o seu computador e depois fazer upload pro servidor, etc.
O script é simples, e para usá-lo você só precisa baixar o arquivo updateDB.php
, configurá-lo colocando o diretório do seu servidor para o qual você deseja que ele baixe a base de dados, e fazer o upload do arquivo modificado para o seu servidor. Depois é só acessar esse arquivo pelo seu navegador que o script será executado, a base de dados será baixada no local especificado, e ainda será descompactada. Só lembrando, no meu caso, o diretório que utilizo é o /home/interpossi/geoip/
, então o meu código vai estar configurado para este diretório.
Veja o código do script:
<?php /* ALTERE ESSE VARIAVEL PARA O DIRETORIO NO SEU SERVIDOR ONDE DEVERA FICAR A BASE DE DADOS GEOIP */ $dir = '/home/interpossi/geoip/'; /* VOCE NAO PRECISA ALTERAR NADA DAQUI EM DIANTE */ $file_source = 'http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz'; $file_target = $dir."GeoLiteCity.dat.gz"; $file_decompressed = $dir."GeoLiteCity.dat"; @set_time_limit(180); /* baixando o arquivo */ $rh = fopen($file_source, 'rb') or die('download_file '. __('error: reading or opening file', 'visitor-maps')); $wh = fopen($file_target, 'wb') or die('download_file '. __('error: cannot write to file, check server permission settings', 'visitor-maps')); $counter = 0; $megs = 1; $every = 1024; while (!feof($rh)) { if (($counter % $every) == 0) { echo '('.$megs.')'; $megs++; } if (fwrite($wh, fread($rh, 1024)) === FALSE) { die('download_file '. __('error: cannot write to file, check server permission settings', 'visitor-maps')); return true; } $counter++; } fclose($rh); fclose($wh); /* descompactando */ $sfp = gzopen($file_target, "rb"); $fp = fopen($file_decompressed, "w"); while ($string = gzread($sfp, 4096)) { fwrite($fp, $string, strlen($string)); } gzclose($sfp); fclose($fp); ?>
Preste atenção: a variável que você precisa modificar é a $dir. Siga o exemplo, não deixando de terminar o caminho do diretório com /
.
Conclusões finais
Bom, espero que seja útil pra vocês, e para a Rosemeire, que me chamou atenção para essas novas APIs.
Se alguém tiver alguma dúvida, alguma sugestão, compartilhem através dos comentários.
E até a próxima.
bacana, rodou numa boa
so nao entendi esse Codigo do estado, qual é o criterio?
07, Distrito Federal, Brasília
15, Minas Gerais, Belo Horizonte
21, Rio de Janeiro, Rio De Janeiro
26, Santa Catarina, Chapecó
31, Tocantins, Taguatinga
que base de informação é essa???
seria bom saber pra poder implementar outras classes junto a esse geoIP
aguardo uma ajuda
[]s
Oi Leandro.
Primeiro, obrigado pelo comentário. Estava em viagem, por isso demorei um pouco a responder.
—
Eu acredito que o "Código do estado", chamado de "Region" pelo GeoIP, seja um número definido arbitrariamente pela MaxMind. Ele é armazenado na base de dados GeoIP, junto com as outras informações.
Esse "código", para os Estados do Brasil, é definido, por exemplo, no arquivo regionvars.php, como sendo:
"01" => "Acre",
"02" => "Alagoas",
"03" => "Amapa",
"04" => "Amazonas",
"05" => "Bahia",
"06" => "Ceara",
"07" => "Distrito Federal",
"08" => "Espirito Santo",
"11" => "Mato Grosso do Sul",
"13" => "Maranhao",
"14" => "Mato Grosso",
"15" => "Minas Gerais",
"16" => "Para",
"17" => "Paraiba",
"18" => "Parana",
"20" => "Piaui",
"21" => "Rio de Janeiro",
"22" => "Rio Grande do Norte",
"23" => "Rio Grande do Sul",
"24" => "Rondonia",
"25" => "Roraima",
"26" => "Santa Catarina",
"27" => "Sao Paulo",
"28" => "Sergipe",
"29" => "Goias",
"30" => "Pernambuco",
"31" => "Tocantins",
Possuindo o "Código do País" e o "Código da Região", é possível obter o nome da região utilizando a seguinte expressão:
$GEOIP_REGION_NAME[$record->country_code][$record->region]
Por exemplo,
$GEOIP_REGION_NAME['BR'][15] deveria retornar "Minas Gerais".
Certo? Dúvida respondida?
Olá Maverick
muito bom o seu artigo!!! Funcionou perfeitamente, porém ao testar no seu código, notei que até a cidade ele retornava, porém no meu código a cidade está vindo vazia.
Você está utilizando a versão lite da base ou a versão comercial?
obrigado,
David Nunes
Olá David. Obrigado pelo comentário.
No código em PHP estou utilizando a versão GeoLite City. Existem duas versões: a GeoLite City e a GeoLite Country. Essa última, tem menos informações, e mostra apenas o país. Para mostrar a cidade, precisamos utilizar o GeoLite City.
Você pode baixar a versão GeoLite City aqui.
Já o código em JavaScript não necessita que baixemos uma base de dados, pois ele utiliza a base de dados comercial, hospedada pela própria MaxMind.
Certo? Respondida sua dúvida?
Já utilizo esse esquema da MaxMind mas nunca encontra minha cidade corretamente!!
Estado e país sempre está certo! Mas a cidade nunca!
Eu não uso no-ip e nada do tipo. Alguém tem alguma dica?
Tudo bom Lucas?
Então, com a minha cidade é bem parecido. A minha Internet é o Oi Velox e sempre que tento me localizar pelo GeoIP aqui em casa o resultado é uma cidade grande vizinha. Muitos dizem que é por que a “central” (backbone, roteador, etc) da minha Internet fica lá nessa cidade vizinha. Já quando eu vou pra faculdade (que fica aqui na minha cidade e usa a Internet da RNP (Rede Nacional de Pesquisa)) o GeoIP identifica minha cidade corretamente.
Então acho que a gente pode pensar que no banco de dados do GeoIP estão cadastrados os provedores de Internet (e não os usuários, obviamente) e que, quando a gente se localiza pelo GeoIP, na verdade o GeoIP informa a posição do nosso provedor e não a nossa.
Alguém tem outra teoria sobre isso?
P.S.: tente atualizar sua base de dados. Os resultados sempre melhoram depois de atualizar.
Maverick, show de bola este post, me ajudou muito.
Gostei do artigo, bem claro e didático.
Tenho uma dúvida: através do GeoIP eu consigo filtrar o país de origem e redirecionar o usuário para uma outra página ?
Com os textos em sua língua nativa?
Caso seja possível, você pode mostrar como ficaria o código?
Olá Uoster, obrigado por seu comentário.
Então, existem N maneiras de se fazer isso e cada uma tem um benefício em relação a outra.
Como exemplo didático, você poderia fazer algo assim na sua página inicial:
header(‘Location: http://www.seusite.com.br/‘ . strtolower($localizacao->country_code) . ‘/’);
Dessa forma, se o usuário estiver nos Estados Unidos, ele será redirecionado para “www.seusite.com.br/us/”, se ele estiver no Brasil, será redirecionado para “www.seusite.com.br/br/”, e assim por diante.
Dê uma pesquisada em “redirect using geoip” que você vai encontrar vários exemplos, principalmente “redirect using mod_geoip and mod_rewrite”, ok?
Dank!