Adressdaten Geocodieren mit Google Maps API und php

Oft ist es gewünscht Adressdaten aus einer Datenbank auf einer Karte darzustellen. Insbesondere die Google Maps API, Google Earth, OpenStreemaps und OpenLayers bieten dafür fertige Lösungen. Der Knackpunkt dabei aber: Es müssen Längen und Breitengrad bekannt sein um eventuell über eine KML Datei die Daten entsprechend bereit stellen zu können.

Hierfür biete Google mit der Google Maps API eine entsprechende Funktion mit der sich die Adressdaten in Längen und Breitengrade übersetzen lassen. Hier ein paar grundlegende Überlegungen zur Ausführung der Geocodierung.
Ihr benötigt in jedem Fall einen Google Maps API Key, diesen könnt ihr hier bekommen.

Adressdaten erweitern

Gehen wir davon aus das wir eine mySQL Datenbank haben mit einer Tabelle in der unsere Adressen sich befinden. Im Beispiel haben wir 3 Spalten in der Tabelle mit den Namen: PLZ, ORT, STRASSE, und eine Spalte mit einem Primärschlüssel ID.  Um später unsere Geo Koordinaten ablegen zu können müssen wir die Tabelle erweitern. Fügt der Tabelle mit dem Admin Tool eurer Wahl zwei Spalten hinzu. Format: FLOAT(10,6). Namen: GEO_LAT und GEO_LNG. In diese beiden Spalten schreiben wir dann die Koordinaten.

php Script

Die folgenden Auszüge aus dem Script dienen als Anregung. Insbesondere wie eine Verbindung zur mySQL Datenbank hergestellt wird und andere Teile zu programmieren sind wird hier nicht im besonderen erklärt!

API URL und API Key festlegen, wird so später auf einfache Art und Weise verwendet:

1
2
define("MAPS_HOST", "maps.google.com");
define("KEY", "enter_your_apikey_here");

Wir setzen uns die URL für die API zusammen:

1
2
$delay = 0;
$base_url = "http://" . MAPS_HOST . "/maps/geo?output=xml" . "&key=" . KEY;

Wir holen uns alle Daten aus der Adressen Tabelle, in unserem Fall alle die noch ohne Koordinaten:

1
$data = mysql_query("Select * From ADRESS Where GEO_LAT = '' or GEO_LNG = ''");

Durch diese Daten werden wir nun durchgehen und diese über die Maps API versuchen mit Koordinaten zu versehen:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
while ( $d = mysql_fetch_array($data) ) {
    echo "GEOCodiere ".$d['ID']\n";
    $geocode_pending = true;
    while ($geocode_pending) {
        //Wir setzen die Adresse aus den Feldern zusammen:
        $address = $d['PLZ']." ".utf8_encode($d['ORT']).", ".utf8_encode($d['STRASSE']);
        //Den Abfrage String zusammensetzen
        $request_url = $base_url . "&q=" . urlencode($address);
        //API abfragen
        $xml = simplexml_load_file($request_url) or die("url not loading");
        //Statuscode und Auswertung
        $status = $xml->Response->Status->code;
        if (strcmp($status, "200") == 0) {
            // Erfolgreich codiert!
            $geocode_pending = false;
            $coordinates = $xml->Response->Placemark->Point->coordinates;
            $coordinatesSplit = split(",", $coordinates);
            // Format: Longitude, Latitude, Altitude
            $lat = $coordinatesSplit[1];
            $lng = $coordinatesSplit[0];
            //Daten in die Tabelle schreiben
            mysql_query("Update ADRESS Set GEO_LAT = '$lat', GEO_LNG= '$lng' Where ID ='$d[ID]'");
        } else if (strcmp($status, "620") == 0) {
            // Abfrage erfolgte zu schnell hintereinander
            $delay += 100000;
        } else {
            // Fehler beim Codieren
            $geocode_pending = false;
            echo "Address " . $address . " failed to geocoded. ";
            echo "Received status " . $status . "\n";
        }
        usleep($delay);
    }
}

Wie ihr seht werten wir in unserem Durchlauf den Statuscode 620 aus. Diesen erhalten wir von der API wenn wir zuviele Anfragen oder Anfragen zu schnell hintereinander stellen. In der Praxis tritt dies zwar nur sehr sehr selten auf, aber man sollte gewappnet sein!
Wie ihr letztlich dieses Script aufbaut und einsetzt bleibt eurer Phantasie überlassen. Wenn man sehr viele Daten codieren möchte wird es als einfaches php script in einer Webseite nicht funktionieren da der Timeout zuschlagen wird. (php Scripte auf dem Webserver werden in der Regel nach x Sekunden unterbrochen wenn sie nicht fertig werden). Da dies an der Command Line (CLI) nicht begrenzt wird kann man dieses Script auch prima dort betreiben, zum Beispiel über CRON unter Linux oder mit einer Batch Datei unter Windows.

Fragen dazu? Starte eine Diskussion im Forum.

3 Comments

  1. Tom

    Danke für Dein Script!
    Genau sowas hab ich gesucht, leider funktioniert es nicht.
    Einmal hab ich einen kleinen Fehler gefunden. In Zeile zwei der Schleife heißt es:
    echo „GEOCodiere „.$d[‚ID‘]\n“;
    heißen muss es meiner Meinung nach aber:
    echo „GEOCodiere „.$d[‚ID‘].“\n“;
    Ein kleiner . und “ fehlen hier vor \n

    Das Script liest sich Zeile für Zeile wirklich einfach und ist soweit auch für mich verständlich.
    Trotzdem wirft das Spript bei mir nur das „DIE-Kommentar aus:
    GEOCodiere … url not loading

    Sind hier URLs und Schnittstellen bei Google geändert worden?!
    Ich bin bei meiner Sucher nach einer Lösung darüber gestolpert, dass die API jetzt vor kurzen geändert wurde.

    Vielleicht bist Du ja etwas fitter hier auf dem Thema wie ich, bin hier am verzweifeln.
    Würde mich über eine Antwort freuen.

    Danke und Gruß aus dem Norden.

  2. Tom

    Was ich bislang raus gefunden hab, die neue XML-URL ist:
    https://maps.googleapis.com/maps/api/geocode/xml?address=YOUR_ADDRESS&key=YOUR_API_KEY

    Geb ich diese URL direkt in den Browser mit der entsprechenden Adresse (PLZ, Ort), dann wird ein XML mit den richtige Geodaten im Browser ausgegeben. Jedoch meldet das Scipt nach wie vor, dass kein öffnen möglich ist.
    Was den API-Key betrifft, bin mir bewusst, dass der vom hinterlegten Server kommen muss. Lokal geht’s jedoch auch ohne Key.
    Kann mir auch gut vorstellen, dass die folgende Zeile nicht mehr sauber verarbeitet wird:

    $xml = simplexml_load_file($request_url) or die(„url not loading“);

    Der DIE-Kommentar kommt auf jedem Fall von hier… Muss der Request eventuell erst auf dem Server gespeichert werden und diese Datei dann wieder geladen und gelesen… Wäre ja wirklich umständlich.
    Aus dem PHP-Handbuch zu dieser Funktion bin ich auch noch nicht schlauer geworden.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.