Março de 2008
Objetivo
Este tutorial descreve os conceitos básicos de como criar KML com dados de valores separados por vírgula (CSV) usando Python. Os dados CSV são um dos formatos de arquivo mais usados atualmente. A maioria das planilhas e bancos de dados pode ler e gravar arquivos CSV. O formato simples pode ser editado em um editor de texto. Muitas linguagens de programação, como Python, têm bibliotecas especiais para ler e gravar arquivos CSV. Portanto, é um ótimo meio para trocar grandes quantidades de dados.
Embora os exemplos de código neste tutorial estejam em Python, eles podem ser adaptados para a maioria das outras linguagens de programação. Este tutorial usa o código de Geocodificação de endereços para uso em KML (link em inglês) para transformar um endereço em coordenadas de longitude/latitude. Ele também usa o novo elemento <ExtendedData>
do KML 2.2 e aproveita a criação de modelos de balão descrita em Adicionar dados personalizados. Por isso, o KML produzido não é compatível com o Google Maps ou outros aplicativos que usam KML, mas o código pode ser adaptado para produzir KML compatível com o Maps.
Dados de amostra
Para este tutorial, use o arquivo google-addresses.csv como um exemplo de arquivo CSV. Esse arquivo tem todos os endereços, números de telefone e fax dos vários escritórios do Google nos EUA. Confira o texto do arquivo:
Office,Address1,Address2,Address3,City,State,Zip,Phone,Fax Headquarters,1600 Amphitheatre Parkway,,,Mountain View,CA,94043,650-253-0000,650-253-0001 New York Sales & Engineering Office,76 Ninth Avenue,,,New York,NY,10011,212-565-0000,212-565-0001 Ann Arbor Sales Office,201 South Division Street,,,Ann Arbor,MI,48104,734-332-6500,734-332-6501 Atlanta Sales & Engineering Office,10 10th Street NE,,,Atlanta,GA,30309,404-487-9000,404-487-9001 Boulder Sales & Engineering Office,2590 Pearl St.,,,Boulder,CO,80302,303-245-0086,303-535-5592 Cambridge Sales & Engineering Office,5 Cambridge Center,,,Cambridge,MA,02142,617-682-3635,617-249-0199 Chicago Sales & Engineering Office,20 West Kinzie St.,,,Chicago,IL,60610,312-840-4100,312-840-4101 Coppell Sales Office,701 Canyon Drive,,,Coppell,TX,75019,214-451-4000,214-451-4001 Detroit Sales Office,114 Willits Street,,,Birmingham,MI,48009,248-351-6220,248-351-6227 Irvine Sales & Engineering Office,19540 Jamboree Road,,,Irvine,CA,92612,949-794-1600,949-794-1601 Pittsburgh Engineering Office,4720 Forbes Avenue,,,Pittsburgh,PA,15213,, Santa Monica Sales & Engineering Office,604 Arizona Avenue,,,Santa Monica,CA,90401,310-460-4000,310-309-6840 Seattle Engineering Office,720 4th Avenue,,,Kirkland,WA,98033,425-739-5600,425-739-5601 Seattle Sales Office,501 N. 34th Street,,,Seattle,WA,98103,206-876-1500,206-876-1501 Washington D.C. Public Policy Office,1001 Pennsylvania Avenue NW,,,Washington,DC,20004,202-742-6520,
Observe como cada linha é uma série de strings de texto separadas por vírgulas.
Cada vírgula delimita um campo, e cada linha tem o mesmo número de vírgulas.
A primeira linha contém os nomes dos campos em ordem. Por exemplo, o primeiro bloco de texto em cada linha é o campo "Office", o segundo "Address1" e assim por diante. O Python pode transformar isso em uma coleção de dicts
chamada DictReader
, que permite percorrer cada linha. Este exemplo de código depende de você conhecer
de antemão a estrutura dos seus dados, mas é possível adicionar
alguns manipuladores básicos para transmitir a estrutura do campo de forma dinâmica.
Analisar o arquivo CSV
O módulo xml.dom.minidom
do Python oferece ótimas ferramentas para criar documentos XML. Como o KML é XML, você vai usar bastante esse módulo neste tutorial. Você cria um elemento com createElement
ou
createElementNS
e anexa a outro elemento com appendChild
.
Estas são as etapas para analisar o arquivo CSV e criar um arquivo KML.
- Importe geocoding_for_kml.py para seu módulo.
- Crie um
DictReader
para os arquivos CSV. ODictReader
é uma coleção dedicts
, um para cada linha. - Crie o documento usando
xml.dom.minidom.Document()
do Python. - Crie o elemento raiz
<kml>
usandocreateElementNS.
. - Anexe ao documento
.
- Crie um elemento
<Document>
usandocreateElement
. - Anexe-o ao elemento
<kml>
usandoappendChild
. - Para cada linha, crie um elemento
<Placemark>
e adicione-o ao elemento<Document>
. - Para cada coluna em cada linha, crie um elemento
<ExtendedData>
e adicione-o ao elemento<Placemark>
criado na etapa 8. - Crie um elemento
<Data>
e adicione-o ao elemento<ExtendedData>
. Dê ao elemento<Data>
um atributo de nome e atribua a ele o valor do nome da coluna usandosetAttribute
. - Crie um elemento
<value>
e adicione-o ao elemento<Data>
. Crie um nó de texto e atribua a ele o valor da coluna usandocreateTextNode
. Anexe o nó de texto ao elemento<value>
. - Crie um elemento
<Point>
e adicione-o ao elemento<Placemark>
. Crie um elemento<coordinates>
e anexe-o ao elemento<Point>
. - Extraia o endereço da linha para que ele seja uma única string neste formato: Address1,Address2,City,State,Zip. Então, a primeira linha seria
1600 Amphitheater Parkway,,Mountain View,CA,94043
. Não tem problema se houver vírgulas juntas. Para fazer isso, é necessário ter conhecimento prévio da estrutura do arquivo CSV e de quais colunas constituem o endereço. - Geocodifique o endereço usando o código geocoding_for_kml.py explicado em Geocodificação de endereços para uso em KML. Isso retorna uma string que é a longitude e a latitude do local.
- Crie um nó de texto e atribua a ele o valor das coordenadas na etapa 14. Em seguida, adicione-o ao elemento
<coordinates>
. - Grave o documento KML em um arquivo.
- Se você transmitir uma lista de nomes de colunas como argumentos para o
script, ele vai adicionar elementos nessa ordem. Se não nos importássemos com a ordem dos elementos, poderíamos usar
dict.keys()
para produzir umlist
. No entanto, odict.keys()
não preserva a ordem original do documento. Para usar esse argumento, transmita a lista de nomes de campos como uma lista separada por vírgulas, assim:python csvtokml.py Office,Address1,Address2,Address3,City,State,Zip,Phone,Fax
Exemplo de código Python
Confira abaixo um exemplo de código para criar um arquivo KML com base em um arquivo CSV usando o Python 2.2. Você também pode fazer o download neste link.
import geocoding_for_kml
import csv
import xml.dom.minidom
import sys
def extractAddress(row):
# This extracts an address from a row and returns it as a string. This requires knowing
# ahead of time what the columns are that hold the address information.
return '%s,%s,%s,%s,%s' % (row['Address1'], row['Address2'], row['City'], row['State'], row['Zip'])
def createPlacemark(kmlDoc, row, order):
# This creates aelement for a row of data.
# A row is a dict.
placemarkElement = kmlDoc.createElement('Placemark')
extElement = kmlDoc.createElement('ExtendedData')
placemarkElement.appendChild(extElement)
# Loop through the columns and create a element for every field that has a value.
for key in order:
if row[key]:
dataElement = kmlDoc.createElement('Data')
dataElement.setAttribute('name', key)
valueElement = kmlDoc.createElement('value')
dataElement.appendChild(valueElement)
valueText = kmlDoc.createTextNode(row[key])
valueElement.appendChild(valueText)
extElement.appendChild(dataElement)
pointElement = kmlDoc.createElement('Point')
placemarkElement.appendChild(pointElement)
coordinates = geocoding_for_kml.geocode(extractAddress(row))
coorElement = kmlDoc.createElement('coordinates')
coorElement.appendChild(kmlDoc.createTextNode(coordinates))
pointElement.appendChild(coorElement)
return placemarkElement
def createKML(csvReader, fileName, order):
# This constructs the KML document from the CSV file.
kmlDoc = xml.dom.minidom.Document()
kmlElement = kmlDoc.createElementNS('http://earth.google.com/kml/2.2', 'kml')
kmlElement.setAttribute('xmlns','http://earth.google.com/kml/2.2')
kmlElement = kmlDoc.appendChild(kmlElement)
documentElement = kmlDoc.createElement('Document')
documentElement = kmlElement.appendChild(documentElement)
# Skip the header line.
csvReader.next()
for row in csvReader:
placemarkElement = createPlacemark(kmlDoc, row, order)
documentElement.appendChild(placemarkElement)
kmlFile = open(fileName, 'w')
kmlFile.write(kmlDoc.toprettyxml(' ', newl = '\n', encoding = 'utf-8'))
def main():
# This reader opens up 'google-addresses.csv', which should be replaced with your own.
# It creates a KML file called 'google.kml'.
# If an argument was passed to the script, it splits the argument on a comma
# and uses the resulting list to specify an order for when columns get added.
# Otherwise, it defaults to the order used in the sample.
if len(sys.argv) >1: order = sys.argv[1].split(',')
else: order = ['Office','Address1','Address2','Address3','City','State','Zip','Phone','Fax']
csvreader = csv.DictReader(open('google-addresses.csv'),order)
kml = createKML(csvreader, 'google-addresses.kml', order)
if __name__ == '__main__':
main()
KML de amostra criado
Confira abaixo um exemplo do KML criado por esse script.
Observe como alguns elementos<value>
têm apenas espaços em branco. Isso acontece porque o campo não tinha dados. Você também pode baixar o exemplo completo aqui.
<?xml version="1.0" encoding="utf-8"?>
<kml xmlns="http://earth.google.com/kml/2.2">
<Document>
<Placemark>
<ExtendedData>
<Data name="Office">
<value>
Headquarters
</value>
</Data>
<Data name="Address1">
<value>
1600 Amphitheater Parkway
</value>
</Data>
<Data name="City">
<value>
Mountain View
</value>
</Data>
<Data name="State">
<value>
CA
</value>
</Data>
<Data name="Zip">
<value>
94043
</value>
</Data>
<Data name="Phone">
<value>
650-253-0000
</value>
</Data>
<Data name="Fax">
<value>
650-253-0001
</value>
</Data>
</ExtendedData>
<Point>
<coordinates>
-122.081783,37.423111
</coordinates>
</Point>
</Placemark>
...
Captura de tela
Confira abaixo uma captura de tela de como esse arquivo KML aparece no Google Earth.
Como cada elemento <Placemark>
não tem <BalloonStyle><text>
nem <description>
, o balão usa um estilo de tabela, com base nos elementos <Data>
.

Consideração sobre a geocodificação
Isso foi mencionado em "Geocodificação de endereços para uso em KML", mas vale a pena repetir. Suas solicitações de geocodificação estarão sujeitas à taxa máxima de consultas do geocodificador e a 15.000 consultas por dia com base no seu IP. Além disso, um código de status 620
será retornado pelo geocodificador se você fizer consultas mais rápido do que ele consegue processar. Uma lista completa de códigos de status está disponível aqui.
Para não enviar consultas muito rapidamente ao geocodificador, especifique um atraso entre cada solicitação de geocodificação. É possível aumentar esse atraso a cada vez que você recebe um status 620
e usar um loop while
para garantir que você geocodificou um endereço antes de iterar para o próximo. Isso significa que, se o arquivo CSV for muito grande, talvez seja necessário modificar o código de geocodificação ou controlar a velocidade de criação de indicadores de lugar e diminuir o ritmo se estiver muito rápido.
Conclusão
Agora você pode usar o Python para criar um arquivo KML com base em um arquivo CSV. Usando o código fornecido, o arquivo KML só vai funcionar no Google Earth. Você
pode modificar para funcionar no Maps e no Earth usando
<description>
em vez de <ExtendedData>
.
Também é fácil converter esse exemplo de código para qualquer
outra linguagem de programação que ofereça suporte a XML.
Agora que você terminou de converter todos os arquivos CSV para KML, confira outros artigos sobre KML, como Usar PHP e MySQL para criar KML e o artigo do guia para desenvolvedores do Google sobre ExtendedData, Adicionar dados personalizados.