O Google oferece um serviço de pesquisa e visualização de mapas e imagens de satélite online, conhecido como Google Maps. Através de dados de terceiros, também oferece serviço de busca de endereços no mapa. O processo de conversão de endereços em coordenadas geográficas é chamado geocodificação. Ou seja, o usuário digita o endereço e o Google procura em sua base de dados, fornecendo CEP, latitude e longitude (o que permite plotar o ponto no mapa) e outras informações. O serviço é chamado Google Geocoding API.
As informações estão dispostas em um arquivo no formato JSON (JavaScript Object Notation), que é um formato leve com o objetivo de troca de informações entre computadores. É constituído de dois tipos de estruturas: coleção de pares nome/valor (conhecidos como objetos e dispostos em chaves {}) e lista ordenada de valores (conhecida como array ou vetor, dispostos entre colchetes []).
Clique no link abaixo e veja um trecho de um arquivo JSON para o endereço do MASP (Museu de Arte de São Paulo: Avenida Paulista, 1578 – São Paulo):
Lembrando que os espaços em branco usam os caracteres “%20” em uma URL. O arquivo desse link pode ser baixado diretamente no terminal Linux através do comando wget. Para ler os campos do arquivo JSON, você pode instalar e usar o comando jq https://stedolan.github.io/jq/ também no terminal. Veja um exemplo de como extrair a latitude, longitude e endereço formatado usando o jq:
longitude=$(cat arquivo_baixado.json | jq '.results[0].geometry.location.lng') latitude=$(cat arquivo_baixado.json | jq '.results[0].geometry.location.lat') endereco=$(cat arquivo_baixado.json | jq '.results[0].formatted_address')
O mesmo resultado pode ser obtido usando python, importando o módulo json. Veja esse exemplo:
import json # Abrir arquivo data = json.load(open(arq1)) # Extrair valores lat/lon latitude = data['results'][0]['geometry']['location']['lat'] longitude = data['results'][0]['geometry']['location']['lng'] endereco = data['results'][0]['formatted_address']
Esses exemplos permitem visualizar a hierarquia de campos utilizados no arquivo para se obter os valores das coordenadas. Latitude e longitude são impressas usando ponto para separar a parte decimal (entre 7 e 8 casas de precisão).
Cruzamento de vias
O formato “TIPO LOGRADOURO,NÚMERO” funciona bem como parâmetro de entrada na API do Google Maps. Inclusive com abreviações e até mesmo pequenos erros de ortografia, o mecanismo de busca do Google permite retornar um resultado bem satisfatório. Se não for informado um número, as coordenadas são relativas ao meio da rua (considerando seu início e fim).
Caso busque o cruzamento de duas ruas, a documentação do Google diz para usar o formato “TIPO LOGRADOURO1 AND TIPO LOGRADOURO2” (ou usar COM em vez de AND para juntar os dois endereços). Isso funciona bem nos EUA, mas no Brasil geralmente retorna só as coordenadas do primeiro endereço fornecido. Além disso, em casos que o algoritmo de busca encontre uma ambiguidade (ou seja, mais de uma resposta com potencial de ser a correta), o campo “results” retornará mais de um endereço.
Considerando essas informações (endereço sem número retorna centro da rua e que pode haver mais de uma resultado), podemos considerar o seguinte algoritmo para estimar a localização do cruzamento de duas ruas:
1. Gravar todos os valores de latitude e longitude possíveis do primeiro endereço;
2. Gravar todos os valores de latitude e longitude possíveis do segundo endereço;
3. Para cada ponto, calcular a distância entre a coordenada (par latitude/longitude) do primeiro e do segundo enndereço, conforme a fórmula
\(d=\sqrt{(lat_1-lat_2)^2+(lon_1-lon_2)^2}\)4. Escolher as duas coordenadas que tiverem menor distância entre si;
5. Calcular a média entre as latitudes e longitudes escolhidas dos dois pontos.
A operacionalização desse algoritmo pode ser feita através de linguagem python, lendo os arquivos baixados do Google Maps e imprimindo os valores das coordenadas – vide último tópico desse post.
Chave para API de geocodificação do Google Maps
Caso trabalhe com muitas conversões, também é importante fazer uma chave no Google (API key). É possível fazer as consultas sem ter uma chave, mas isso tem certas limitações. O limite de requisições por dia é em torno de 500 e uma boa parte delas pode resultar em valor nulo – principalmente se forem feitas uma muito próxima da outra. Com a chave, o limite de solicitações diárias gratuitas aumenta para 2500 – veja mais na página Limites de uso do Google Maps Geocoding API.
Para obter a chave, visite a página de Primeiros passos do “Web Services -> Geocoding API” e clique em “Obter uma chave” para criar um projeto e receber sua sequência de caracteres. Para sua utilização, inclua no link “key=SUA_CHAVE” logo após o sinal de interrogação que vem depois do nome “json”, seguida do caractere “&” para separá-la de outros campos. Usando o mesmo exemplo do MASP, seu link ficaria assim:
http://maps.googleapis.com/maps/api/geocode/json?key=SUA_CHAVE&sensor=false&address=Avenida%20Paulista,%201578,%20Sao%20Paulo
Ao atingir seu limite diário, o arquivo recebido terá status igual a “OVER_QUERY_LIMIT”. Você pode optar por correr o script para os endereços restantes em outro dia ou fazer uma nova API em outro endereço de e-mail ou pagar por novas solicitações.
Scripts para converter muitos endereços
Se você tiver um arquivo CSV com muitos endereços, é útil fazer um script para ler esse arquivo linha a linha, obter o endereço e usá-lo como parâmetro de entrada para a API do Google, de modo a obter as respectivas coordenadas. Os scripts em bash e python, assim como os arquivos de exemplo e uma breve descrição em inglês estão disponíveis no github address2coordinate. Segue aqui uma descrição do algoritmo de ação desses programas.
Primeiro, o shell script “rec_coord.sh” contém as variáveis definindo a chave API e os nomes dos arquivos de entrada e de saída. Em cada linha lida do arquivo de entrada, os campos são separados por ponto e vírgula e gravados em variáveis diferentes. Se a variável referente ao número do endereço (“number”) NÃO cotiver um número, é o caso de aplicar o algoritmo de cruzamento de vias; caso contrário (com número), só montar o endereço comum.
Já para caso com cruzamento de duas vias, deve-se montar um link para cada um dos campos e baixar seu respectivo arquivo JSON, “gmaps1.json” e “gmaps2.json”, que servirão como parâmetros de entrada para o script em python (read_json.py, conforme algoritmo descrito anteriormente). No caso do endeço com número, o script em python recebe como argumento os nomes “gmaps.json” e “NA” para o nome do segundo arquivo.
Caso a solicitação à API resulte em erro, o arquivo JSON terá poucas linhas (geralmente 5). Enquanto o número de linhas for baixo, deve ser feita uma nova solicitação, até que apareça um resultado não-nulo. Caso o endereço esteja escrito errado, nunca vai retornar um arquivo bom. Por isso, o loop possui um contador para limitar o número de solicitações em 10. Ao atingir esse limite, o loop é quebrado.
Finalmente, o resultado (se for válido) será impresso no arquivo de saída; caso contrário (se a variável com as coordenadas continua nula como na inicialização do loop), a linha original será impressa em outro arquivo para análise posterior.
Obs.: esse post originalmente postado em 2014 foi totalmente reformulado para trabalhar usando python (em vez do jq) e incluir a questão de encontrar as coordenadas do cruzamento de duas vias, além dos mecanismos para lidar com falhas de requisição. Devido ao tamanho, e com o intuito de facilitar a cooperação de outros programadores, os scripts estão hospedados no GitHub.
boa tarde,
Voce pode disponibilizar esse arquivo csv para ter como exemplo?
Obrigado.
Oi Sadrake,
Coloquei no final do post duas linhas do arquivo CSV que usei com o script, você pode copiá-las para um arquivo de texto e salvar como “input.csv” para fazer os testes. Espero que ajude.
esse limite será do site que esta requisitando? ou da conta do usuário logado no google?
Creio que esse limite seja por IP, ou seja, se você realizar mais consultas mas de outro computador ou mudar seu IP de saída (usando tor, por exemplo), ele pensa que é outro usuário. Não precisa de conta no Google para usar essa ferramenta deles.
boa tarde, estou precisando fazer um cadastro de visitantes, onde consigo formar um grupo de visitantes fechado por uma “categoria” dentro do formulário, no raio de 10km do cadastro de cada visitante, eu consigo fazer isso acontecer?
Boa tarde, Fábio. Uma ideia é, primeiro, converter cada endereço cadastrado em latitude/longitude. Depois, calcular um intervalo máximo e mínimo de latitude e longitude para um visitante e fazer a verificação para cada um dos outros cadastrados se ele está dentro desse limite: se estiver, grava em uma coluna dizendo o CPF dele. Daí você tem todos os visitantes que estão perto dele.
Para medir a distância entre duas coordenadas de uma forma mais precisa, existe um shell script nesse link que pode ajudar: http://www.unix.com/shell-programming-and-scripting/250356-geographical-distance-between-long-lat-bash.html
Creio que existe uma técnica matemática mais poderosa que essas iterações, mas no momento pensei isso.
Alguém que conseguiu rodar os csv. poderia me dar um help ?
47997468859