Marzo 2008
Obiettivo
Questo tutorial illustra le nozioni di base su come creare KML dai dati CSV (valori separati da virgole) utilizzando Python. I dati CSV sono uno dei formati file più diffusi in uso oggi. La maggior parte dei fogli di lavoro e dei database può leggere e scrivere file CSV. Il suo formato semplice può essere modificato in un editor di testo. Molti linguaggi di programmazione, come Python, hanno librerie speciali per leggere e scrivere file CSV. Pertanto, è un ottimo mezzo per lo scambio di grandi quantità di dati.
Sebbene
gli esempi di codice in questo tutorial siano in Python, possono essere
adattati alla maggior parte degli altri
linguaggi di programmazione. Questo tutorial utilizza il codice di Geocoding
Addresses for Use in KML per trasformare un
indirizzo in coordinate di longitudine/latitudine. Utilizza anche il nuovo elemento <ExtendedData>
di KML 2.2 e sfrutta i modelli di fumetti descritti in Aggiunta di dati personalizzati. Pertanto, il file KML prodotto non è attualmente
supportato in Google Maps o in altre applicazioni che utilizzano file KML, ma il
codice può essere adattato per
produrre file KML compatibili con Maps.
Dati di esempio
Per questo tutorial, utilizza il file google-addresses.csv come file CSV di esempio. Questo file contiene tutti gli indirizzi, i numeri di telefono e i numeri di fax dei vari uffici Google negli Stati Uniti. Ecco il testo del file:
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,
Nota come ogni riga sia una serie di stringhe di testo separate da virgole.
Ogni virgola delimita un campo; ogni riga ha lo stesso numero di virgole.
La prima riga contiene i nomi dei campi in ordine. Ad esempio,
il
primo blocco di testo in ogni riga è il campo "Ufficio", il secondo
"Indirizzo1" e così via. Python può trasformare questo in una raccolta di dicts
chiamata DictReader
che ti consente di
scorrere ogni riga. Questo esempio di codice si basa sulla conoscenza
preventiva della struttura dei dati, ma potresti aggiungere
alcuni gestori di base per trasmettere la struttura dei campi in modo dinamico.
Analisi del file CSV
Il modulo xml.dom.minidom
di Python fornisce ottimi strumenti per creare documenti XML e, poiché KML è XML, lo utilizzerai molto in questo tutorial. Crea un elemento con createElement
o
createElementNS
e aggiungilo a un altro elemento con appendChild
.
Di seguito sono riportati i passaggi per analizzare il file CSV e creare un file KML.
- Importa geocoding_for_kml.py nel tuo modulo.
- Crea un
DictReader
per i file CSV.DictReader
è una raccolta didicts
, uno per ogni riga. - Crea il documento utilizzando
xml.dom.minidom.Document()
di Python. - Crea l'elemento radice
<kml>
utilizzandocreateElementNS.
- Aggiungilo al documento
.
- Crea un elemento
<Document>
utilizzandocreateElement
. - Aggiungilo all'elemento
<kml>
utilizzandoappendChild
. - Per ogni riga, crea un elemento
<Placemark>
e aggiungilo all'elemento<Document>
. - Per ogni colonna di ogni riga, crea un elemento
<ExtendedData>
e aggiungilo all'elemento<Placemark>
che hai creato nel passaggio 8. - Crea un elemento
<Data>
e aggiungilo all'elemento<ExtendedData>
. Assegna all'elemento<Data>
un attributo di nome e assegnagli il valore del nome della colonna utilizzandosetAttribute
. - Crea un elemento
<value>
e aggiungilo all'elemento<Data>
. Crea un nodo di testo e assegnagli il valore della colonna utilizzandocreateTextNode
. Aggiungi il nodo di testo all'elemento<value>
. - Crea un elemento
<Point>
e aggiungilo all'elemento<Placemark>
. Crea un elemento<coordinates>
e aggiungilo all'elemento<Point>
. - Estrai l'indirizzo dalla riga in modo che sia una singola
stringa in
questo
formato: Indirizzo1,Indirizzo2,Città,Stato,Codice postale. Quindi la prima riga
sarebbe
1600 Amphitheater Parkway,,Mountain View,CA,94043
. È normale che ci siano virgole una accanto all'altra. Tieni presente che per farlo è necessario conoscere in anticipo la struttura del file CSV e quali colonne costituiscono l'indirizzo. - Geocodifica l'indirizzo utilizzando il codice geocoding_for_kml.py spiegato in Geocodifica degli indirizzi da utilizzare in KML. Restituisce una stringa che corrisponde alla longitudine e alla latitudine della posizione.
- Crea un nodo di testo e assegnagli il valore delle coordinate del passaggio 14, quindi aggiungilo all'elemento
<coordinates>
. - Scrivi il documento KML in un file.
- Se trasmetti un elenco di nomi di colonne come argomenti allo script, quest'ultimo aggiungerà gli elementi in questo ordine. Se non ci interessasse
l'ordine degli elementi, potremmo utilizzare
dict.keys()
per produrre unlist
. Tuttavia,dict.keys()
non conserva l'ordine originale del documento. Per utilizzare questo argomento, trasmetti l'elenco dei nomi dei campi come elenco separato da virgole, nel seguente modo:python csvtokml.py Office,Address1,Address2,Address3,City,State,Zip,Phone,Fax
Codice Python di esempio
Di seguito è riportato un codice di esempio per la creazione di un file KML da un file CSV utilizzando Python 2.2. Puoi anche scaricarlo qui.
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 di esempio creato
Di seguito è riportato un esempio del file KML creato da questo script.
Nota come alcuni<value>
elementi contengano solo spazi bianchi. Questo perché il campo non
contiene dati. Puoi anche scaricare l'esempio completo qui.
<?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>
...
Screen shot
Di seguito è riportato uno screenshot dell'aspetto del file KML in Google Earth.
Poiché ogni elemento <Placemark>
non ha <BalloonStyle><text>
e nessun elemento <description>
, il fumetto utilizza per impostazione predefinita uno stile di tabella, basandosi sugli elementi <Data>
.

Considerazioni sulla geocodifica
Questo aspetto è stato menzionato in "Geocodifica degli indirizzi da utilizzare in KML",
ma è bene ripeterlo. Le tue richieste di geocodifica saranno
soggette alla frequenza massima di query del geocoder e a 15.000 query al giorno in base al tuo IP. Inoltre, il geocoder restituirà un
codice di stato 620
se lo interroghi più velocemente di quanto possa
gestire. Un elenco completo dei codici di stato è disponibile qui.
Per assicurarti di non inviare query troppo rapidamente al geocodificatore, puoi
specificare un ritardo tra ogni richiesta di geocodifica. Puoi aumentare questo ritardo ogni volta che ricevi uno stato 620
e utilizzare un ciclo while
per assicurarti di aver geocodificato correttamente un indirizzo prima di passare al successivo. Ciò
significa che se il file CSV è molto grande, potresti dover
modificare il codice di geocodifica o tenere traccia della velocità di creazione
dei segnaposto e rallentarla se è troppo elevata.
Conclusione
Ora puoi utilizzare Python per creare un file KML da un file CSV. Utilizzando il
codice fornito, il file KML funzionerà solo in Google Earth. Puoi modificarlo per utilizzarlo sia in Maps che in Earth utilizzando
<description>
anziché <ExtendedData>
.
È anche facile convertire questo esempio di codice in qualsiasi altro linguaggio di programmazione che supporti XML.
Ora che hai terminato la conversione di tutti i file CSV in KML, ti consigliamo di consultare altri articoli su KML, ad esempio Utilizzo di PHP e MySQL per creare file KML e l'articolo della Guida per gli sviluppatori Google su ExtendedData, Aggiunta di dati personalizzati.