openplanningtools.net > PythonGeocoder

PythonGeocoder - Pythongestützte Geocodierung von Adressdaten mittels der GoogleAPI

Inhaltsverzeichnis

  1. PythonGeocoder - Pythongestützte Geocodierung von Adressdaten mittels der GoogleAPI
    1. Wie soll dies funktionieren?
    2. Technische Umsetzung
    3. Python Basics
      1. Python IDLE unter Windows XP
      2. Python IDLE unter Ubuntu
      3. Sonstige Infos zu Python
      4. Python Lizenz und Community
    4. Erste Schritte mit Python
      1. Erste Programmier Übung
      2. Python-Basics anhand von Beispielen erlernen
        1. Beispiel 1: Definiere Strings als Variablen und gebe dies dann aus. In einem weiteren Schritt wird auf dies Stringvariablen zugegriffen.
        2. Beispiel 2: Nummern und Zahlen
        3. Beispiel 3: Listen
        4. Beispiel 4: Wie verwendet man die eingebaute Hilfe?
        5. Beispiel 5: Arbeiten mit Modulen:
        6. Beispiel 6: If, elif, else und Operatoren:
        7. Beispiel 7: while und for Schleifen.
        8. Beispiel 8: Objektorientierung
  2. Der Python Geocoder
    1. Programmdownload und Start
      1. Wie wird das Programm verwendet?
      2. Was passiert bei Programmverwendung intern?
    2. Wie wurde das Programm erzeugt?
      1. Grundsätzliche Funktionsweise des Skriptes
    3. Links und Quellen

Autor: Ronald Weberndorfer

Es gibt in der Planung oft das Problem, dass Daten nur mit Adressen und ohne Koordinaten vorhanden sind. Um mit diesen Daten raumrelevante Analysen durchführen zu können wird dazu die geographische Verortung benötigt. Da dies bei vielen Anbietern sehr kostenintensiv ist wird hier eine Möglichkeit vorgestellt Adressen mittels Google zu geocodieren und diese dann in weiterer Folge mit der GoogleAPI zu visualisieren.

Wie soll dies funktionieren?

  1. Es wird eine Adresse via Eingabe in ein Pythonformular eingetragen.
  2. Geocodierung erfolgt mittels Google (Es können Adressen oder Koordinaten eingegeben werden).
  3. Die Geokoodierten Adressen werden in einer Karte (Html-Seite) als Marker (Punkte) angezeigt.
  4. Es wird auch möglich sein dem Punkt in Google eine Popuptext hinzuzufügen (ev. auch mit Adresse und Koordinaten vorbefüllt) und somit diverse Informationen bereitzustellen.
  5. Es soll so aufgebaut sein, dass man eine Eingabemaske für die Adresse sowie für die Informationen (Informationen von Usern) hat, welche dann Angezeigt werden.
  6. Die Punkte werden immer zu den schon vorhandenen Daten hinzugefügt.

Technische Umsetzung

  1. Manuelle Eingabemaske wird mit Python erstellt – läuft also lokal auf einem Rechner.
  2. Automatischer Export der Html-Datei aus Python.
  3. Thats It - Html kann angezeigt werden!

Python Basics

Bevor man mit Python arbeiten kann muss man folgende Installation durchführen, sofern nicht Python bereits auf dem Rechner installiert ist.

Python IDLE unter Windows XP

  1. Installiere Python v2.6: http://www.python.org/download/releases/ (Offizielle Python Seite) - Das IDLE wird bei Windows automatisch mitinstalliert.

  2. Das IDLE kann über Start/Alle Programme/Python 2.6/IDLE aufgerufen werden

Python IDLE unter Ubuntu

Python ist vorinstalliert, nicht allerdings das IDLE. Um dies auch zur Verfügung zu haben muss man folgendes durchführen:

  1. Öffene Terminal
  2. Folgenden Befehl eingeben: sudo apt-get install python python-tk idle und Enter!

  3. Folgende Frage: Do you want to continue [Y/n] mit y und Enter beantworten.

  4. Dadurch wird das IDLE und das benötigte tk-Modul (Tkinter-Modul) installiert.
  5. Das IDLE kann dann über Aplications/Programming/IDLE aufgerufen werden.

Sonstige Infos zu Python

WICHTIG: Will man mit Python Plattformunabhängig programmieren, muss man bei der Funktionsauswahl darauf achten, dass diese jeweils für die gewünschten Betriebssysteme auch verfügbar sind.
Beispiel dazu: Unter http://docs.python.org/release/2.6.6/library/os.html?highlight=os.startfile#os.startfile ist ersichtlich das etwa die Funktion os.startfile() nur für Windows verfügbar ist. Es ist in der Doku immer unter "Availability" die Prozessverfügbarkeit je Plattform beschrieben. Der nächste os -Befehl system (siehe vorigen Link) ist demnach für Unix, Windows verfügbar.

Python Lizenz und Community

Alle Python releases sind Open Source (siehe dazu http://www.opensource.org/ bezüglich der Open Sourve Definition). Für weitere Informationen zur Lizenz und der Entwicklung von Python siehe: http://docs.python.org/license.html

Unter http://www.python.org/community/ ist weitere Information (Mailinglists, Newsgroups, Wiki's, etc.) zur "Python Software Foundation" zu finden welche als die Community für Python verstanden werden kann.

Erste Schritte mit Python

Nach der Installation von Python kann es los gehen.

Starte: IDLE (Python GUI)
Es öffnet sich das "Python Shell" - IDLE (Integrated Development Environment) ist eine Python-Entwicklungsumgebung.
Unter dem Menüpunkt File/New Window kann man eine neue Python-Programmdatei erstellt werden.
Nachdem diese Datei als *.py gespeichert wurde, kann sie über den Menüpunkt Run/Run Module im Python Shell ausgeführt werden.
Alternativ zum IDLE gibt es auch andere Entwicklungsumgebungen (wie bereits oben erwähnt verwende ich Eclipse) siehe dazu: http://wiki.python.org/moin/PythonEditors.

Erste Programmier Übung

Mit # wird ein Kommentar im Skript begonnen!
Nachstehend werde ich Python Skripte anführen in welche nach und nach verschiedene Funktionen erläutert werden.
Am Besten werden diese Funktionen immer gleich in einer Übungsdatei probiert um auch die Ergebnisse sofort zu sehen. Durch drücken auf Run/Run Module bzw. F5 kann die testdatei.py dann ausgeführt werden (siehe dazu auch auf nachstehende Abbildung).

1_python_shell.jpg

Nachstehend werden die Befehle immer hier im Wiki wie folgt als Skripttext beschrieben. Wenn man im Wiki auf "Toggle line numbers" drückt wird dem Text eine Zeilennummerierung vorangestellt. Grundsätzlich ist der Text so formatiert, dass dieser direkt in Python übernommen (kopiert) werden kann.

Zeilennummern ein/ausschalten
# "ich bin ein Kommentar"
print "Hallo" # gibt Hallo im Python Shell aus

""" Blockkommentar:
kann mehrere Zeilen lang sein.
bla bla ...
"""

Dieser Befehl (print "Hallo") kann auch direkt im Python Shell eingegeben werden ohne eine *.py Datei zu erstellen. (Enter startet den Befehl)
Beispiel:

Zeilennummern ein/ausschalten
>>> print "Hallo"
Hallo
>>>

Da nun die grundsätzliche Funktionsweise von Shell und Python-Programmdatei klar sein sollte, können wir nun mit den tatsächlichen Funktionen beginnen. Es wird nachstehend versucht die wichtigsten Funktionen aufzuzeigen und kurz zu erläutern.

Python-Basics anhand von Beispielen erlernen

Grundsätzlich gibt es folgende Datentypen: String, Nummer und Listen

Beispiel 1: Definiere Strings als Variablen und gebe dies dann aus. In einem weiteren Schritt wird auf dies Stringvariablen zugegriffen.

Zeilennummern ein/ausschalten
# definiere Varaibelen:
test1 = "string1" # Variblenname = Variableninhalt (die Zuweisung erfolgt ueber "=")
test2 = 'string2'
test3 = "Mein Name ist 'Hubert'"

# Gebe Variablen aus:
print test1 + " " + test2
print test3

# Die String Varaible kann auch mehrmals aufgerufen werden:
print test1 * 3

# Zugriff auf Variablen:
# Mit Eckiger Klammer definiert man die Dauer des Ablaufs.
print test1[0:1]    # lese den ersten Buchstabe der Variable test1 aus.
print test1[0]      # Achtung: es wird bei 0 zu zaehlen begonnen!
print test1[:-1]    # Wenn man keine Position festlegt wird vom Anfang an gestartet.
                    # wenn ein "-" vor die Position steht wird vom Ende aus nach gezaehlt.
print test1[:]

Hinweis: es ist immer sinnvoll alles in skripten mit kleinbuchstaben zu schreiben um tippfehlern vorzubeugen.

Beispiel 2: Nummern und Zahlen

Zeilennummern ein/ausschalten
ganzzahl = 10
kommazahl = 10.0
plus = ganzzahl + kommazahl - 5.4
print plus

Beispiel 3: Listen

Zeilennummern ein/ausschalten
meineliste1 = ["Eintrag","Eintrag2","ball","rever","hans"]
print meineliste1
meineliste2 = [] #leere Liste
meineliste1.sort(key=str.lower, reverse=False)  # sortiere meine liste unabhaengig von gr. und kleinschreibung aufsteigend
                                                # siehe dazu Beispiel 4 - die Hilfefunktion

print meineliste1

print len(meineliste1)  # Laenge der Liste
print len(meineliste2)
print type(meineliste1) # liest den Datentype aus
print max([ganzzahl,kommazahl])

Beispiel 4: Wie verwendet man die eingebaute Hilfe?

Am Besten verwendet man die Hilfe nicht in einem Skript sondern per Direkteingabe in das Python Shell!

Zeilennummern ein/ausschalten
print dir(__builtins__)                # Hilfe Funktionsauflistung
print dir(__builtins__.list)           # alle Funktionen die unter "list" verfügbar sind
print dir(__builtins__.list.sort)      # die Unterfunktion sort in list (sortiere Liste)
print __builtins__.list.sort.__doc__   # __doc__ ist immer die Doku zur Funktion

Built In Functions sind vorgegebene Funktionen in Python.
Weitere Informationen/Hilfe zu den Funktionen sind ist unter http://docs.python.org/ zu finden.
Siehe auch http://www.python.org/doc/ für andere Python Versionen.

Beispiel 5: Arbeiten mit Modulen:

Was sind Module:
Die Aufteilung des Quelltextes in verschiedene Teile sind Module. In Python kann jeder seine eigenen Module einbinden oder aus dem umfangreichen Pool der bereits mitgelieferten eines auswählen. Es besteht natürlich auch die Möglichkeit Module von Drittanbietern zu verwenden.

Einbinden von externen Modulen: nachstehend habe ich alle für den PythonGeocoder benötigten Module aufgeführt. Dies müssen natürlich am Begin der Datei geladen werden damit sie in weiterer Folge auch verwendet werden können.

Zeilennummern ein/ausschalten
import shutil           # einzelnen Laden von einem Modul
import os,urllib, csv   # Laden von mehrere Modulen gleichzeitig
                        # Beim Laden mit import wird ein Namensraum fuer alle Funktionen erstellt

from Tkinter import *   # Durch Laden mit from wird kein Namensraum erstellt und es sind alle diese Funktionen "global" in diesem Programm verfuegbar.
import webbrowser       # Lade ein weiteres Modul

Modul

Funktion

"shutil"

ist zum kopieren von files

"os"

Files anlegen, lesen, löschen

"urllib"

zum parsen von html oder xml Seiten

"csv"

csv schreiben, lesen, bearbeiten

"Tkinter"

einfache GUI Erzeugung

"webbrowser"

öffnen des Webbrowsers und anzeigen einer Website

Da der Tkinker für die GUI Erzeugung verwendet wird, hier noch zwei hilfreiche Links:
http://www.wspiegel.de/tkinter/tkinter_index.htm
http://www.tutorialspoint.com/python/python_gui_programming.htm

Beispiel 6: If, elif, else und Operatoren:

Es gibt in Pyhton folgende Operatoren:

x == y

x ist gleich y

x != y

x ist ungleich y

x > y

x ist größer y

x < y

x ist kleiner y

x >= y

x ist größer gleich y

x <= y

x ist kleiner gleich y

or

Boolsches Oder

and

Boolsches Und

not

Boolsches Nicht

in

Mitgliedschaftstest

Die einfachste Variante ist die Fallunterscheidung durch eine "IF" Abfrage. Wenn diese positiv ausfällt dann wird die Funktion ausgeführt ansonsten nicht. bei nichtzutreffen wird dann die nächste abfrage abgearbeitet (z.B.: "elif" oder "else"). Else wir immer am Ender der Abfrage verwendet um bei nichtzutreffen aller vorherigen Bedingungen doch noch eine Antwort vom Programm zurückzuerhalten.

WICHTIG: Beim Arbeiten mit "if" oder "Schleifen" sowie sonstigen Definitionen in Python muss immer der Tabulator richtig gesetzt werden. Dieser ersetzt bei Funktionen die Klammern und es können diese dementsprechend weggelassen werden. Diese Art der Einrückung funktioniert natürlich auch über mehrere Hierarchieebenen dementsprechend werden dann einfach mehrere TAB gesetzt. Siehe dazu nachstehendes if-Beispiel.
Aber ACHTUNG es ist immer auf eine korrekte Einrückung mittels Tabulatoren zu achten da andernfalls die Skripte nicht ordnungsgemäß funktionieren.

Zeilennummern ein/ausschalten
testa = 5 == 5    # gibt Antwort True aus
testb = 5 == 6    # gibt Antwort False aus
print testa
print testb

if testa == True:                               # pruefe ob die Variable testa "True" ist
    print "TEST A ist wahr!"    # gibt Antwort aus
    if testb == False:          # hierachisch nachgeordnete pruefung - laeuft erst wenn die erste (testa == True) zugetroffen ist
        print "Test B ist nicht wahr"   # Antwort auf 2te pruefung


x = 2
if x == 1:                   # pruefe Variable x
    print "Zahl ist 1"
elif x == 2 or x == 3:
    print "Zahl ist 2 oder 3"
else:
    print "Zahl > 3"

Beispiel 7: while und for Schleifen.

Eine Schleife (engl. loop) ermöglicht es ein Codeabschitt mehrmals hintereinander ablaufen zu lassen. Es gibt dazu zwei Schleifentypen (for und while).

Die "while" Schleife besteht aus einer Bedingung am Beginn welche solange diese zutrifft die in der Schleife stehenden Funktionen so lange wiederholt bis diese nicht mehr zutrifft (oder wahr ist).
Die "for" Schleife hat ebenfalls im Kopf stehen was diese machen soll der einfachste Fall dabei ist einfach eine Zählschleife (siehe dazu Beispiel unten). Weiters hat man hier im vergleich mit der "while" allerdings auch noch andere Möglichkeiten wie etwa über eine Liste oder Text (siehe Beispiel unten) zu iterieren.

Zeilennummern ein/ausschalten
# Schleife laeuft so lange x kleiner 10 ist
x = 5
while x < 10:
    print x
    x = x + 1
print "while-Schleife ist fertig"

# Schleife laeuft von 25 - 31 in 2er Schritten -range(start, stop, step)
for i in range(25,32, 2):
    print i
print "for Schleife ist fertig"

# Schleife ueber Text
for c in "mein Text":
    print c

# Schleife ueber Liste
liste=[94165,165,546,46,4,4,465]
for i in liste:
    print i
print "for Schleife ueber Liste ist fertig"

Beispiel 8: Objektorientierung

In diesem Beispiel wird nun das wichtigste von Python vorgestellt. Objektorientierung bedeutet das Quellcode wiederverwendet werden kann indem dieser zu sogenannten Objekten zusammengefasst wird und der Zugriff auf dieses "Codepaket" nur über bestimmte definierte Schnittstellen erfolgen kann. Siehe dazu das nachstehende Beispiel in dem "meinefunktion" definiert wird, bevor allerdings die Objektorientierte Variante vorgestellt wird arbeite ich diese auch in "normalen" Code auf.


Normaler Code:

Zeilennummern ein/ausschalten
      # normal
x = 200
textausgabe = " wurde als Wert definiert."
x_str =  str(x)             # wandle x(Zahl) in einen String um
print x_str + textausgabe   # erzeuge Beispielvariable
x_1 = x + 0.555
print x_1

print "\n" # Zeilenumbruch in der Ausgabe


Objektorientiertet Code:

Zeilennummern ein/ausschalten
      # objektorientiert
def meinefunktion(x,textausgabe):
    x_str =  str(x)
    print x_str + textausgabe
    x_1 = x + 0.9999
    print x_1
    global x_1          # wandle Variable in Globale Variable um damit man auch ausserhalb darauf zugreifen kann - siehe dazu 3 Zeilen weiter unten

meinefunktion(200+5," wurde als Wert definiert.") # rufe Funktion mit zwei Uebergabeparametern auf
print "Ende der objektorientierten Funktion"

# die Folgenden Schritte sind Zusatzinformation und werden nicht
print x_1    # verwende Globale Variable ausserhalb der definierten Funktion.
x_1 = 1000  # ueberschreibe (globale) Variable
print x_1
del x_1     # loesche (globale) Variable

Der Python Geocoder

In der nachstehenden Grafik ist die Oberfläche des Geocoders ersichtlich.
geocoder_gui.jpg

Programmdownload und Start

Bitte Geocoder.zip downloaden und den Ordner "prog_data" an entsprechender Stelle speichern.
In diesem ZIP sind folgende Dateien enthalten:

Datei

Inhalt

prog_data\start.dat

Statischer Teil 1 (Anfang) der HTML Datei

prog_data\end.dat

Statischer Teil 2 (Ende) der HTML Datei

prog_data\Geocoder_start.py

Diese Datei enthält das gesamte Programm des Geocoders. Wenn man diese Datei startet kommt in die Oberfläche des oben Abgebildeten Geocoders.


Wie eine Python Datei ausgeführt wird, ist unter Python Basics bereits erklärt.

HINWEIS zur Kompatibilität: Das Programm wurde in Windows XP erstellt und ist dort fehlerfrei lauffähig.
Es läuft grundsätzlich auch auf Ubutu, allerdings kann es sein, dass hier aufgrund des Thinker-GUI Modules kleine BUG's in der Anzeige der Statusmeldungen zu finden sind! Weites kann es bei Ubunto vorkommen, dass je nach Spracheinstellungen und Version Fehler bei den Sonderzeichen (ß,ä,ö, etc.) auftreten können.

Wie wird das Programm verwendet?

  1. In das erste Eingabefeld können Adressen (z.B.: operngasse 11, wien) oder WGS84 (LAT/LON) Koordinaten (z.B.: 47.5, 13.5) eingegeben werden.
    Nach der Eingabe wird der Button "Geocodieren" gedrückt, welcher mittels Google entweder die Adresse Geocodiert oder einer Koordinate (nach Möglichkeit) eine Adresse zuordnet. Das Ergebnis wird GRAU hinterlegt an der Oberfläche (Statusfenster) ausgegeben. Falls die Adresse nicht korrekt zurückgegeben wird kann durch ändern der Schreibweise erneut die gleiche Adresse gesucht werden.

  2. Das Statusfenster welches sich in Mitte der Oberfläche befindet gibt Auskunft über die letzten gesetzten Aktionen im Tool.
  3. Wurde eine korrekte Adresse ausgegeben kann diese (jeweils die letzt welche in der Anzeige ist) mit einem Titel bzw. Inhalt (sofern dies Html ist kann alles eingebunden werden z.B.: auch Bilder) versehen werden und gemeinsam mit diesen Informationen durch drücken auf den Button "Ja, Speichern" in der Datenbank (csv-Datei) abgelegt werden.
  4. Die vorangegangenen Schritte kann man wiederholen und entsprechend viele Punkte in die Grunddatei aufnehmen.
  5. Möchte man alle Punkte nun in einer Karte anzeigen muss man den Button "Ja, HTML Erzeugen" drücken um die Outputdatei automatisch generieren zu lassen.
  6. Wenn dies abgeschlossen ist, kann mit dem Button "HTML Aufrufen" die Karte im Browser geöffnet werden.
  7. Noch ein Hinweis: Alle Buttonfunktionalitäten stehen auch über das Menü im Kopf der Anwendung zur Verfügung.

Was passiert bei Programmverwendung intern?

Folgende Dateien werden von dem Programm automatisiert erzeugt:

Datei

Inhalt

prog_data\db.csv

In dieser Datei werden alle Geocodierungen (Input und Output), die Geokoordinaten sowie die Informationen zu Titel und Inhalt für den jeweiligen Punkt abgelegt.
Möchte man einen Datenpunkt löschen kann dies mittels Texteditor in dieser Datei durchgeführt werden. Wenn man mit einer leeren Vorlage beginnen möchte kann diese Datei einfach gelöscht werden da diese automatisch vom Programm wieder erzeugt wird.

prog_data\map.html

Dies ist das "Ergebnis"- wenn man auf den Button "HTML Erzeugen" drückt, in diese Datei wird die "Website" abgelegt.
Diese Datei wird jedes mal beim Drücken des Button "HTML Erzeugen" überschrieben, bzw. neu erstellt und kann demnach auch gelöscht werden ohne das Probleme im Programm auftreten.

Wie wurde das Programm erzeugt?

Nachfolgen ist der Source Code des Python Geocoder zu finden. Ich habe versucht diesen mit entsprechenden Kommentaren zu versehen um ihn nachvollziehbar zu machen.

Ein Teil der "Insert Funktion - Button Geocodieren" wurde nicht von mir erstellt, ich habe diesen Code von "Get lat/long coordinates of an address from Google Maps" - M.Keranen (gLatLong.py) übernommen und entsprechend für meine Bedürfnisse ergänzt und angepasst.
Quelle: http://code.activestate.com/recipes/498128/
Das herauslesen der Adresse und sonstige Funktionalität wurden von mir erstellt.

Grundsätzliche Funktionsweise des Skriptes

Dieser Code ist nur in Verbindung mit den "start.dat" und "end.dat" im Ordner "..\\prog_data\\" lauffähig, siehe dazu unter Download.
Diese Dateien werden im Pythonscript für die Erzeugung der Html Seite verwendet. Der mittlere Teil wird dynamisch mittels einer Schleife Erzeugt siehe dazu im Pythonscript bei Funktion (def html_erzeugen():).

  1. Alle benötigten Funktionen (Geocode {Koordinaten und Adressermittlung}, Anwendung Beenden, Daten Speichern/Appenden, HTML Output erzeugen, HTML bzw. WIKI öffnen, About Menü ) werden als objektorientierte Funktion definiert.
  2. Zwischen den Funktionen Interagierende Variablen sind als "globale" definiert um auf diese entsprechend zugreifen zu können.
  3. Nach dem Funktionsaufbau werden alle diese Funktionen in ein GUI eingebettet, welches mittels Tkinter erzeugt wurde.
  4. Die Buttons aus dem GUI rufen die jeweils dafür zuvor definierten Funktionen auf.
  5. Die Funktionen geben immer Statusmeldungen an das Textfeld in der Mitte der Applikation aus.

Da der Tkinker für die GUI Erzeugung verwendet wird, hier noch zwei hilfreiche Links:
http://www.wspiegel.de/tkinter/tkinter_index.htm
http://www.tutorialspoint.com/python/python_gui_programming.htm

Zeilennummern ein/ausschalten
###########################################################################
#  Geocodierung und Visualisierung von Adressdaten mittels der GoogleAPI  #
#  Autor: Ronald Weberndorfer                                             #
#  Datum: 10.01.2011                                                      #
#  Infos: http://ourproject.org/moin/projects/openplanning/PythonGeocoder #
###########################################################################

# Lade benoetigte Module
import os, urllib, csv, shutil, webbrowser
from Tkinter import *

# erzeuge globale Variablen
global addr
addr = ""
global lat
lat = ""

# setze Pfad und Dateinamen
global pfad
pfad = "../prog_data/"
global data
data = pfad + "db.csv"
global data2
data2 = pfad + "db_2.csv"


# definiere Insert Funktion - Button Geocodieren
def Insert():
    global addr
    addr = text.get()   #lade Inhalt des Textfeldes
    if addr == "":      #pruefe Eingabe
        list.insert(0.0, "## Bitte geben sie eine Adresse ein! ## \n")
    else:
        ##### Geocoder Start ####
        url = ''
        if addr[0]=='(':
            center = addr.replace('(','').replace(')','')   # loesche Klammern aus addr
            global lat
            global lng
            lat,lng = center.split(',')     # erzeuge 2 Variablen aus center
            url = 'http://maps.google.com/maps?q=%s+%s' % (lat,lng)
        else:
            # Encode query string into URL
            url = 'http://maps.google.com/?q=' + urllib.quote(addr) + '&output=js'
            # 2 Moeglichkeiten zur Printausgebe der Variable url:
            #print '\nQuery: %s' % (url)    # Aufruf der an Google gesendet wird
            #print "\nQuery: " + str(url)   # Aufruf der an Google gesendet wird
            # Get XML location
            xml = urllib.urlopen(url).read()    # lese xml
            if '<error>' in xml:                # Fange Fehlercode von Google ab
               print '\nGoogle cannot interpret the address.'
            else:
                # lese lat/long aus xml mittels Parser aus
                lat,lng = 0.0,0.0
                center = xml[xml.find('{center:{')+13:xml.find('}',xml.find('{center'))]
                center = center.replace('lat:','').replace('lng:','')
                lat,lng = center.split(',')
                url = 'http://maps.google.com/maps?q=%s+%s' % (lat,lng)
                ## lese Adresse mittels Parser aus
                start =  xml.find('laddr:"')
                adr = xml[start:start + 200]
                end = adr.find("geocode")
                fin = adr[7: end-2]

                # definiere globale Variablen
                global lati 
                lati = float(lat)
                global longi
                longi = float(lng)
                global adresse_neu
                adresse_neu = fin
                global liste
                liste = (addr, lati, longi, adresse_neu)         
                #print liste
                
                ## pruefe Geocode und oeffne Adresse im Browser
                #if url<>'':
                #    print 'Map: %s' % (url)
                #    os.startfile(url)      # funktioniert nur unter Windows
                #    webbrowser.open(url)
                
        ##### Ende Geocoder #####
                
        if adresse_neu == "":       #pruefe Geocodierung - ist eine Adresse vorhanden
            list.insert(0.0, "### Es wurde mit dieser Adresse keine Koordinate gefunden, bitte korrigieren sie die Schreibweise\nund versuchen sie es erneut! ###\n")    # Fehlermeldung
        else:                       # wenn eine Adresse gefunden wurde wird dies in der Verlaufsliste ausgegeben
            list.insert(0.0, "\n")
            list.insert(0.0, "Eingabe: " + addr + "\n")
            list.insert(0.0, "Ausgabe: "+ adresse_neu +"\n")
            list.tag_add("here", "1.9", "1.80")
            list.tag_config("here", background="grey")
            text.delete(0,END)    

# Beende die Anwendung
def ende():
    root.destroy()

# Funktion Button Speichern
def ja_speichern():
    if addr == "":              # Pruefung - wurde bereits geocodiert?
        list.insert(0.0, "Bitte zuerst eine Adresse Geokodieren!\n")   
    else:
        # erzeuge popupinhalt:
        titel = "<h3>" + titelfeld.get() + "</h3>"
        inhalt = inhaltsfeld.get() + "<br><br>"
        popup = titel + inhalt

        # pruefe ob das File neu erstellt wird oder nur einen neue Zeile eingefuegt wird
        vorhanden = os.path.exists(data)
        # schreibe in Database      
        if vorhanden == False:
            # erzeuge neues File und schreibe Dateninhalt
            id = 1                  
            file_wr =open(data,'a+b', buffering=0)
            csv_writer = csv.writer(file_wr, delimiter=";")
            liste = (id, addr, lati, longi, adresse_neu, popup)         
            csv_writer.writerow(liste)
            file_wr.close()
        else:           
            # Schreibfunktion
            file_wr =open(data2,'a+b', buffering=0)
            csv_writer = csv.writer(file_wr, delimiter=";")
                                
            # lese Altdaten ein
            filealt = open(data,'rb')
            csv_reader_alt = csv.reader(filealt, delimiter=';')
            id = 1
            for row in csv_reader_alt:
                #print row
                id = id + 1
                # schreibe bestehende Daten
                csv_writer.writerow(row)
            #print id
            
            # schreibe neue Daten dazu
            liste = (id, addr, lati, longi, adresse_neu, popup)         
            csv_writer.writerow(liste)
            # schliesse Schreib- und Lesefunktion
            file_wr.close()
            filealt.close()
            
            shutil.copyfile(data2, data)    # kopiere data2 wegen append und ueberschreibe data
            os.remove(data2)                # loesche data2
                       
        list.insert(0.0, "## Adresse wurde gespeichert! ## \n") # gib Stausmeldung am GUI aus
        titelfeld.delete(0,END)     # loesche Inhalt des Titelfeld
        inhaltsfeld.delete(0,END)   # loesche Inhalt des Inhaltsfeld


# Erzeuge aus der "csv" Datenbank ein HTML- File fuer die Visualisierung der Daten
def html_erzeugen():
    if lat == "":
        list.insert(0.0, "Bitte zuerst eine Adresse Geokodieren!\n")
    else:
        # erzeuge html File
        start = pfad + "start.dat"      # statische Teil der HTML Datei (beginn)
        end = pfad + "end.dat"          # statische Teil der HTML Datei (ende)

        # Beginn und Ende der Html sind "fix" und werden deshalb aus externen Files eingelesen
        # diese Teile koennen natuerlich je nach Bedarf angepasst werden
        # lade html1
        in_file = open(start,"r")
        start_text = in_file.read()
        in_file.close()
        # lade html2
        in_file = open(end,"r")
        end_text = in_file.read()
        in_file.close()
        
        filealt = open(data,'rb')
        csv_reader_alt = csv.reader(filealt, delimiter=';')
        id = 1
        # lese den Inhalt der csv Datein Spaltenweise ein
        for row in csv_reader_alt:
            id = int(row[0])
            addr = row[1]
            lati = row[2]
            longi = row[3]
            adresse_neu = row[4]
            popup = row[5]
                        
            #erzeuge daraus fuer jedes Element einen Marker (Pin) fuer die Google Karte
            popup_adresse = "Adresse: " + adresse_neu + "<br> Lat: " + str(lati) + "<br>Lon: " + str(longi) + "<br>ID: " +str(id)
            var1 = '\t\tvar point' + str(id) + ' = new GPoint(' + longi + ', ' + lati + ');\n'
            var2 = '\t\tvar html' + str(id) + ' = "' + popup + popup_adresse + '"\n'
            var3 = '\t\tvar beck' + str(id) + ' = new GMarker(point' + str(id) + ');\n'
            var4 = '\t\tGEvent.addListener(beck' + str(id) + ', "click", function(){beck' + str(id) + '.openInfoWindowHtml(html' + str(id) + ')});\n'
            var5 = '\t\tmap.addOverlay(beck' + str(id) + ');'
            center_last_point = '\n\n\t\tmap.setCenter(new GLatLng(' + lat + ', ' + lng + '), 13);\n'  # die Karte wird auf folgenden Punkt zentriert
            marker = var1 + var2 + var3 +  var4 +  var5

            # fuege in der Schleife fuer jede Zeile einen Marker hinzu
            if id == 1:
                marker_alt = marker
            else:
                marker_alt = marker_alt + "\n\n" + marker
                
        marker = marker_alt
               
        # erzeuge HTML-File    
        html = start_text + '\n\n' + marker + center_last_point + end_text
        #print html
        html_out = pfad + "map.html"
        out_file = open(html_out,"w")
        out_file.write(html)
        out_file.close()
        list.insert(0.0, "## HTML Output wurde erzeugt! ## \n") 

# oeffne Html in der Standardanwendung des Betriebssystems
def html_oeffnen():
    list.insert(0.0, "## HTML wird im Browser gestartet ## \n")
    html_offnen = pfad + "map.html"
    #os.startfile(html_offnen)  # funktioniert nur unter Windows
    webbrowser.open(html_offnen)

# oeffne Hilfe im WIKI
def hilfe():
    list.insert(0.0, "## Onlinehilfe wird im Browser geladen ## \n")
    online = "http://ourproject.org/moin/projects/openplanning/PythonGeocoder#Der_Python_Geocoder"
    #os.startfile(online)       # funktioniert nur unter Windows
    webbrowser.open(online)
    
# About Menu
def about():
    top = Tk()
    top.title('About')
    L1 = Label(top, text="Python Geocoder/ HTML Viewer\n Version 1.0 \nDatum: 10.01.2011\nAutor: Ronald Weberndorfer\n\nInhalt:\n Mit diesem Programm kann man Adressen in Google erfassen\nund diese dann mit Titel und Inhalt in einer Html-Karte darstellen.\n Geocodiert und Visualisiert wird mit GoogleMaps.\n\n Weitere Infos + Sourcecode: \nhttp://ourproject.org/moin/projects/openplanning/PythonGeocoder")
    L1.pack()
    top.mainloop()

#### Definition aller GUI FELDER ####
root = Tk()
root.title('Geocoder')

# Menu in der Anwendung
menubar = Menu(root)
filemenu = Menu(menubar, tearoff=0)
filemenu.add_command(label="Geocodieren", command = Insert)
filemenu.add_command(label="Eintrag Speichern", command = ja_speichern)
filemenu.add_command(label="HTML erzeugen", command = html_erzeugen)
filemenu.add_command(label="HTML aufrufen", command = html_oeffnen)
filemenu.add_separator()
filemenu.add_command(label="Beenden", command=ende)
menubar.add_cascade(label="Datei", menu=filemenu)
root.config(menu=menubar)

helpmenu = Menu(menubar, tearoff=0)
helpmenu.add_command(label="Online Hilfe", command=hilfe)
helpmenu.add_command(label="About...", command=about)
menubar.add_cascade(label="Hilfe", menu=helpmenu)
# ende menu

frame = Frame(root)
frame.pack()

# Ueberschrift 1
titel = Label(root, text='Bitte geben Sie eine Adresse oder WGS84-Koordinate (z.B: 47.5, 13.5):',font=('Arial',10), fg='black')
titel.pack()
# Eingabefeld 1
text = Entry(root, bg = 'white', width=80, relief=SUNKEN)
text.pack()
# Button Geocodieren
button = Button(root, text = "Geocodieren", width=20, command = Insert)
button.pack()
# Geocode Verlauf - alle Statusmeldugen werden hier angezeigt
list = Text(root, relief=SUNKEN)
list.pack()

# Ueberschrifen und Eingabefelder fuer Titel und Inhalt des Popups
feld = Label(root, text='Titel:     ',font=('Arial',8), fg='black')
feld.pack()
titelfeld = Entry(root, bg = 'white', width=50, relief=SUNKEN)
titelfeld.pack()
feld2 = Label(root, text='Inhalt:     ',font=('Arial',8), fg='black')
feld2.pack()
inhaltsfeld = Entry(root, bg = 'white', width=50, relief=SUNKEN)
inhaltsfeld.pack()

# Ueberschrift 2
titel = Label(root, text = '     Soll die grau hinterlegte Adresse mit Titel + Inhalt in der Datenbank gespeicher werden?     ',font=('Arial',8), fg='black')
titel.pack()

# Button Speichern
ja = Button(root, width=20, text='JA, Speichern', command = ja_speichern)
ja.pack()

# Ueberschrift 3
titel1 = Label(root, text = '     Soll das Output-HTML erzeugt werden?     ',font=('Arial',8), fg='black')
titel1.pack()
# Button HTML Erzeugen
html_erzeugen = Button(root, width=20, text='JA, HTML Erzeugen', command = html_erzeugen)
html_erzeugen.pack()
# Button HTML im Browser oeffnen
html_aufrufen = Button(root, width=20, text='HTML Aufrufen', command = html_oeffnen)
html_aufrufen.pack()

# Gesamtschleife fuer GUI
root.mainloop()

Alle für die Erstellung der oben beschriebenen Software benötigten Quellen sind in der nachstehenden Tabelle aufgelistet:

Diese Links sind auch bereits im Text mit entsprechender weiterer Erläuterung zu finden.

OpenPlanningTools: PythonGeocoder (zuletzt geändert am 2012-02-03 11:27:22 durch mk089144206200)