Avatar billede tinem Novice
16. august 2007 - 10:17 Der er 13 kommentarer og
1 løsning

Geocoding af danske adresser

Jeg har lavet denne side http://www.tinemuller.dk/googlemap/gaia/tutorial_I.htm, hvor jeg bruger databasen mysql og har hidtil fundet koordinaterne fra http://www.findvej.dk/ og manuelt indsat dem i databasen, MEN nu skulle Geocoder fra Google virke i Danmark og nu mangler jeg hjælp til hvilke koder jeg skal bruge og hvor for at få denne til at finde koordinaterne udfra adresserne i databasen og lagre disse, og så skal det være sådan at Geocoderen KUN skal søge efter koordinater på de adresser som ikke hidtil er fundet. Jeg ved det er muligt, men har altså brug for hjælp til disse koder og håber nogen kan hjælpe.

Et simpelt eksempel med disse koder ville være alletiders, fordi så kan jeg bruge det til en masse andre sider, hvor man f.eks. har et excel-ark med navne og adresser, og altså "bare" mangler koordinaterne.

/Tine
Avatar billede tinem Novice
16. august 2007 - 10:55 #1
Jeg har tidligere lavet denne side med hjælp fra Peter Brodersen http://www.tinemuller.dk/googlemap/geocoder_DK/, som også viser forskellen fra findvej og google geocoder.

Denne linje gør at den KUN søger i Denmark
geocoder.setBaseCountryCode("dk");
Avatar billede olebole Juniormester
16. august 2007 - 15:20 #2
<ole>

Dokumentationen ligger her:
    http://www.google.com/apis/maps/documentation/#Geocoding_Examples

Der er ikke forskel på at finde en adresse i Australien eller Danmark  =)

/mvh
</bole>
Avatar billede tinem Novice
16. august 2007 - 16:24 #3
>>ole
>>Der er ikke forskel på at finde en adresse i Australien eller Danmark  =)

Det var Peter Brodersen som gjorde mig opmærksom på dette. Hvis du ser under det link som du selv henviser til, står der noget under New!

Har du selv Geocoded en site, som jeg må studere for at se DINE koder?
Avatar billede olebole Juniormester
16. august 2007 - 16:43 #4
Jeg har lavet et par stykker, men de ligger bag login  :o|

Det, der står under 'New', handler bare om at prioritere det område, du viser i din viewport. Hvad er det præcist, du ikke kan finde ud af?
Avatar billede olebole Juniormester
16. august 2007 - 18:47 #5
Du kan evt. tjekke denne her:
    http://www.eksperten.dk/spm/788865#rid6837152
Avatar billede tinem Novice
17. august 2007 - 14:23 #6
Ja så prøvede jeg at kopiere dine koder som du henviser til, men der skal jo nok rettes noget mere, fordi dine koder nævner specifikke adresser og mine adresser står jo i en mysql database, right?

Men jeg spurgte jo om råd her på Eksperten, fordi jeg IKKE vidste hvordan man gjorde, men ved fælles hjælp kan vi måske finde ud af det? Bruger du ikke Geocoder med database nøjagtigt som jeg gerne vil bruge det?

Koderne er kopieret til denne fil http://www.tinemuller.dk/folkebiblioteker/tutorial_I.htm som indeholder en masse adresser UDEN koordinater.
Avatar billede olebole Juniormester
17. august 2007 - 15:49 #7
At dine adresser står i en MySQL-database, gør ingen forskel ... så skriver du jo bare et array som dette ud i filen:

    var addresses = [
        "1060 West Addison Street, Chicago, IL",
        "99, rue de Rivoli, Paris 75001",
        "Oder, DE",
        "Piazza della Scala, Milano 20121",
        "London, UK",
        "1600 Pennsylvania Avenue, Washington, DC",
        "A totally bogus address"
    ];

- blot med dine adresser, hentet fra DB'en.

Filen, jeg viser i den anden tråd, er en videreudvikling af det, som cblayout skrev. Derfor outputtes i XML ... jeg kunne ligeså godt have outputtet en del af en sql-fil.

Hvormange adresser drejer det sig om? Det er ikke en fremgangsmåde, jeg vil anbefale for tusindvis af adresser. Du skal tænke på, at Google er eksperter i logging - og Google er eksperter i at erkende og tolke mønstre.

Du skal nok ikke sætte dig ret mange aftener og suge flere tusind adresser på få minutter, før kontoen er lukket  ;o)
Avatar billede olebole Juniormester
17. august 2007 - 16:49 #8
Jeg går udfra, du har hver adresse liggende i DB'en med følgende felter: [id], [gadenavn], [nummer], [postnummer] ... [hvad-ved-jeg]

Så kan du skrive denne JavaScript-kode ud:

    var addresses = [
        [123, "1060 West Addison Street, Chicago, IL"],
        [456, "99, rue de Rivoli, Paris 75001"],
        [789, "Oder, DE"],
        [234, "Piazza della Scala, Milano 20121"],
        [345, "London, UK"],
        [456, "1600 Pennsylvania Avenue, Washington, DC"],
        [567, "A totally bogus address"]
    ];

- med denne PHP-kode:

var addresses = [
<?
$sql = "SELECT `id`, `gadenavn`, `nummer`, `postnummer` FROM `TABEL_NAVN`";
$res = mysql_query( $sql ) or die ( mysql_error() );

$a = array();
while ($row=mysql_fetch_assoc($res)) {
    $a[] = "[".$row["id"].", \"".$row["gadenavn"]." ".$row["nummer"].", ".$row["postnummer"]."\"]";
}

print implode(",\r\n\t", $a);
?>
];

Så kan du prøve at skrive dette i en fil med GMap-script:

<pre id="message">## Adresse opdatering:

</pre>


<script type="text/javascript">
if (GBrowserIsCompatible()) {
    var reasons=[];
    reasons[G_GEO_SUCCESS]            = "Success";
    reasons[G_GEO_MISSING_ADDRESS]    = "Missing Address: The address was either missing or had no value.";
    reasons[G_GEO_UNKNOWN_ADDRESS]    = "Unknown Address:  No corresponding geographic location could be found for the specified address.";
    reasons[G_GEO_UNAVAILABLE_ADDRESS]= "Unavailable Address:  The geocode for the given address cannot be returned due to legal or contractual reasons.";
    reasons[G_GEO_BAD_KEY]            = "Bad Key: The API key is either invalid or does not match the domain for which it was given";
    reasons[G_GEO_TOO_MANY_QUERIES]  = "Too Many Queries: The daily geocoding quota for this site has been exceeded.";
    reasons[G_GEO_SERVER_ERROR]      = "Server error: The geocoding request could not be successfully processed.";
    reasons[403]                      = "Error 403: Probably an incorrect error caused by a bug in the handling of invalid JSON.";
   
    function getUniq(nLen) {
        nLen = typeof nLen=="number" ? nLen : 8;
        var a = [], c = "9876543210abcdefghijklmnopqrstuvwxy0123456789";
        nClen = c.length;
        for (var i=0; i<nLen; i++) a[i] = c.charAt( Math.floor(Math.random()*nClen) );
        return a.join("");
    }
   
    function GeoCoderObject() {
        this.id = "GeoObj_" + getUniq() + GeoCoderObject.nGeoCounter++;
        this.onRecieve = function(){};
        this._oGeoCoder = new GClientGeocoder();
        return this;
    }
    GeoCoderObject.nMaxObjects = 20; // Maximalt antal af samtidige request-objekter
    GeoCoderObject.nGeoCounter = 0;
    GeoCoderObject.oGeoCoders = {};
    var _p = GeoCoderObject.prototype;
    _p.getAddress = function(aSearch) {
        var xml = "", me = this, search = aSearch[1];
        this.nAddressID = aSearch[0];
        this._oGeoCoder.getLocations(search, function (result) {
            // If that was successful
            if (result.Status.code == G_GEO_SUCCESS) {
                // Lets assume that the first marker is the one we want
                var p = result.Placemark[0].Point.coordinates;
                var lat=p[1];
                var lng=p[0];
               
                xml = "UPDATE `[TABEL_NAVN]` SET `lat`='" + lat + "', `lng`='" + lng + "' WHERE `id`='" + me.nAddressID + "';\r\n";
            }
        // ====== Decode the error status ======
            else {
                var reason="Code "+result.Status.code;
                if (reasons[result.Status.code]) {
                    reason = reasons[result.Status.code]
                }

                xml = "## Fejl på flg. adresse: '" + search + "' :: [" + reason + "]\r\n";
            }
            me.onRecieve(xml, me.id);
            result = xml = null;
        });
    }
    _p.destroy = function() {
        for (var x in this) if (x!="destroy") this[x] = null;
        this.destroy = null;
    }

    var addresses = [
        [123, "1060 West Addison Street, Chicago, IL"],
        [456, "99, rue de Rivoli, Paris 75001"],
        [789, "Oder, DE"],
        [234, "Piazza della Scala, Milano 20121"],
        [345, "London, UK"],
        [456, "1600 Pennsylvania Avenue, Washington, DC"],
        [567, "A totally bogus address"]
    ];
    function writeAddress(sXml, sId) {
        document.getElementById("message").firstChild.nodeValue += sXml;
        GeoCoderObject.oGeoCoders[sId].destroy();
        GeoCoderObject.oGeoCoders[sId] = null;
        delete GeoCoderObject.oGeoCoders[sId];
        GeoCoderObject.nGeoCounter--;
        if (addresses.length==0 && GeoCoderObject.nGeoCounter==0) {
            document.getElementById("message").firstChild.nodeValue += "\r\n## ================================================================\r\n## Slut på opdatering."
        }
        else loadGeoCoders();
    }
    function loadGeoCoders() {
        var o = null;
        while (addresses.length>0 && GeoCoderObject.nGeoCounter<=GeoCoderObject.nMaxObjects) {
            o = new GeoCoderObject();
            o.onRecieve = writeAddress;
            GeoCoderObject.oGeoCoders[o.id] = o;
            o.getAddress(addresses.shift());
        }
    }
   
    loadGeoCoders();
   
} else { // display a warning if the browser was not compatible
    alert("Sorry, the Google Maps API is not compatible with this browser");
}
</script>

Det vil skrive en kode ud, som du kan kopiere over i en *.sql-fil, som du kan køre på din DB og opdatere denne (HUSK at lave en backup først).

Husk også lige på at gøre det behersket. Jeg har ikke tjekket, om dette overhovedet er lovligt i forhold til brugeraftalen. Det må du naturligvis først sikre dig, inden du begynder at suge  ;o)
Avatar billede tinem Novice
19. august 2007 - 15:51 #9
olebole jeg er MEGET taknemmelig over at du gerne vil hjælpe mig, men jeg kan altså ikke finde ud af, hvor I dine koder jeg skal ændre noget for at få det til at virke. Måske kunne du uploade en fil med .txt i endelsen, hvor du med rød farve skriver hvor ændringerne skal være?
Jeg kan se at du nok har besøgt Mike Williams side http://econym.googlepages.com/geomulti.htm og den har jeg også prøvet for at teste om det virker med de danske adresser, men det gør det ikke http://www.tinemuller.dk/folkebiblioteker/tines_geocoder_test.html, det virker kun på de engelske adresser og jeg ved ikke hvorfor?:-( 

Jeg har uploaded de filer som du ikke kan se indholdet af ved at teste min side http://www.tinemuller.dk/folkebiblioteker/tutorial_I.htm, måske kan det hjælpe dig til at rådgive mig videre.:-)

http://www.tinemuller.dk/folkebiblioteker/tutorial_I.php.txt
http://www.tinemuller.dk/folkebiblioteker/tutorial_testxml.php.txt
http://www.tinemuller.dk/folkebiblioteker/folkebiblioteker.sql

/Tine
Avatar billede olebole Juniormester
19. august 2007 - 19:12 #10
Nej, jeg har ikke besøgt det pågældende link. Koden, jeg har skrevet, er som sagt en videreudvikling af den kode, cblayout skrev i den anden tråd - så han har nok kikket bag det link. Personligt ville jeg have skrevet det på en anden måde - men for ikke at gøre forvirringen større, holdt jeg mig bare til den kode, han selv havde skrevet i tråden  =)

Jeg manglede faktisk selv geo-koordinater til omkring 100 adresser i min DB - og brugte derfor koden ovenfor til at hente dem med, efter jeg havde skrevet den her. Det skete i løbet af ganske få sekunder, så jeg er helt sikker på, den fungerer.

Jeg kikker på dine filer lidt senere - jeg skal lige have noget at spise først. Finder vi ikke ud af det i dén forbindelse, må du gerne skrive til mig. Du kan nå mig på: mit nickname - efterfulgt af 'en krøllet elefantnæse' - gmail - et punktum og com  :D
Avatar billede olebole Juniormester
20. august 2007 - 01:42 #11
Dette burde være tilpasset din DB:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml">
<head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
    <title>Google Maps</title>
    <script src="http://maps.google.com/maps?file=api&amp;v=2&amp;key=DIN_GOOGLE_NØGLE_HER" type="text/javascript"></script>
  </head>
  <body onunload="GUnload()">

<button onclick="getCoordinates()">TEST</button>
<pre id="message">## Adresse opdatering:

</pre>


<script type="text/javascript">
function getCoordinates() {
    if (GBrowserIsCompatible()) {
        var reasons=[];
        reasons[G_GEO_SUCCESS]            = "Success";
        reasons[G_GEO_MISSING_ADDRESS]    = "Missing Address: The address was either missing or had no value.";
        reasons[G_GEO_UNKNOWN_ADDRESS]    = "Unknown Address:  No corresponding geographic location could be found for the specified address.";
        reasons[G_GEO_UNAVAILABLE_ADDRESS]= "Unavailable Address:  The geocode for the given address cannot be returned due to legal or contractual reasons.";
        reasons[G_GEO_BAD_KEY]            = "Bad Key: The API key is either invalid or does not match the domain for which it was given";
        reasons[G_GEO_TOO_MANY_QUERIES]  = "Too Many Queries: The daily geocoding quota for this site has been exceeded.";
        reasons[G_GEO_SERVER_ERROR]      = "Server error: The geocoding request could not be successfully processed.";
        reasons[403]                      = "Error 403: Probably an incorrect error caused by a bug in the handling of invalid JSON.";
       
        function getUniq(nLen) {
            nLen = typeof nLen=="number" ? nLen : 8;
            var a = [], c = "9876543210abcdefghijklmnopqrstuvwxy0123456789";
            nClen = c.length;
            for (var i=0; i<nLen; i++) a[i] = c.charAt( Math.floor(Math.random()*nClen) );
            return a.join("");
        }
       
        function GeoCoderObject() {
            this.id = "GeoObj_" + getUniq() + GeoCoderObject.nGeoCounter++;
            this.onRecieve = function(){};
            this._oGeoCoder = new GClientGeocoder();
            return this;
        }
        GeoCoderObject.nMaxObjects = 20; // Maximalt antal af samtidige request-objekter
        GeoCoderObject.nGeoCounter = 0;
        GeoCoderObject.oGeoCoders = {};
        var _p = GeoCoderObject.prototype;
        _p.getAddress = function(aSearch) {
            var xml = "", me = this, search = aSearch[1];
            this.nAddressID = aSearch[0];
            this._oGeoCoder.getLocations(search, function (result) {
                // If that was successful
                if (result.Status.code == G_GEO_SUCCESS) {
                    // Lets assume that the first marker is the one we want
                    var p = result.Placemark[0].Point.coordinates;
                    var lat=p[1];
                    var lng=p[0];
                   
                    xml = "UPDATE `locations` SET `lat`='" + lat + "', `lng`='" + lng + "' WHERE `id`='" + me.nAddressID + "';\r\n";
                }
            // ====== Decode the error status ======
                else {
                    var reason="Code "+result.Status.code;
                    if (reasons[result.Status.code]) {
                        reason = reasons[result.Status.code]
                    }
   
                    xml = "## Fejl p\u00e5 flg. adresse: '" + search + "' :: [" + reason + "]\r\n";
                }
                me.onRecieve(xml, me.id);
                result = xml = null;
            });
        }
        _p.destroy = function() {
            for (var x in this) if (x!="destroy") this[x] = null;
            this.destroy = null;
        }
   
    var addresses = [

<?
// Ret til korrekte DB-informationer:
$connection = mysql_connect("SERVER", "USER_NAME", "PASS_WORD");
mysql_select_db("DATA_BASE_NAVN", $connection);

$sql = "SELECT `id`, `adresse`, `postnummer`, `by` FROM `folkebiblioteker` WHERE `lat`<1";
$res = mysql_query( $sql ) or die ( mysql_error() );

$a = array();
while ($row=mysql_fetch_assoc($res)) {
    $a[] = "[".$row["id"].", \"".$row["adresse"].", ".$row["postnummer"]." ".$row["by"]."\"]";
}

print implode(",\r\n\t", $a);
?>

    ];
        function writeAddress(sXml, sId) {
            document.getElementById("message").firstChild.nodeValue += sXml;
            GeoCoderObject.oGeoCoders[sId].destroy();
            GeoCoderObject.oGeoCoders[sId] = null;
            delete GeoCoderObject.oGeoCoders[sId];
            GeoCoderObject.nGeoCounter--;
            if (addresses.length==0 && GeoCoderObject.nGeoCounter==0) {
                document.getElementById("message").firstChild.nodeValue += "\r\n## ================================================================\r\n## Slut p\u00e5 opdatering."
            }
            else loadGeoCoders();
        }
        function loadGeoCoders() {
            var o = null;
            while (addresses.length>0 && GeoCoderObject.nGeoCounter<=GeoCoderObject.nMaxObjects) {
                o = new GeoCoderObject();
                o.onRecieve = writeAddress;
                GeoCoderObject.oGeoCoders[o.id] = o;
                o.getAddress(addresses.shift());
            }
        }
       
        loadGeoCoders();
       
    } else { // display a warning if the browser was not compatible
        alert("Sorry, the Google Maps API is not compatible with this browser");
    }
}
</script>
  </body>

</html>

Læg mærke til, du selv skal sætte din Google-key ind i JavaScript-tagget.
Udfyld også de rigtige DB-informationer ved MySQL-kaldet. Så burde dokumentet fungere  =)

Når koordinaterne er hentet, kører du dem som sql-kommando mod databasen i din phpMyAdmin eller, hvad du nu bruger til DB-vedligeholdelse.

Når du har gjort det, reloader du dokumentet i browseren, hvorved evt. adresser, der ikke kunne findes koordinater til ved første forsøg, skrives ind i JS-array'et - og du kan så prøve at hente dem endnu engang. Somme tider lykkes det ikke Google ved første forsøg, men somregel ved andet - og du kan jo altid prøve en tredie.
Er der efter tre forsøg stadig adresser, du ikke kan hente koordinater til, bør du først tjekke stavning - og derefter evt. hente dem manuelt.

Fidusen er, at du kun henter de adresser i databasen, som har et 'lat' felt, hvis værdi er under 1. Det betyder, at du anden og tredie gang ikke henter de adresser, du allerede har fundet koordinater til:
    SELECT `id`, `adresse`, `postnummer`, `by` FROM `folkebiblioteker` WHERE `lat`<1
Avatar billede tinem Novice
20. august 2007 - 11:45 #12
WOW olebole - jeg er fuld af beundring for det script du har lavet. Tusind tak.

Nu er jeg jo lidt nysgerrig over hvordan du fandt frem til netop disse koder, fordi når jeg sammenligner med Mike Williams http://econym.googlepages.com/geomulti.htm, så er de jo ikke identisk.
Avatar billede olebole Juniormester
20. august 2007 - 13:30 #13
Selvtak. Det var denne kode, jeg tog udgangspunkt i:
    http://www.eksperten.dk/spm/788865#rid6837052

Så opbyggede jeg den lidt anderledes, så den blev det, man kalder objektorienteret. Dvs, at jeg skriver en 'motor' (et JavaScript-objekt), der kan hente koordinatsættet tilhørende en bestemt adresse. Denne 'motor' kan jeg så klone, så mange gange, jeg har lyst - og lade hver især hente et koordinatsæt.
Når én 'motor' kan hente èt koordinatsæt på ca. 1,7 sekund og jeg kloner den 20 gange, kan det samlede program altså hente 20 koordinatsæt på ca. 1,7 sekund.

Samtidig lod jeg så PHP hente adresserne i din database og efterfølgende udskrive JavaScript-array'et fra den originale kode - som jeg tror, brugeren 'cblayout' fra det andet spørgsmål har fundet hos Mike Williams.

Hvordan jeg fandt frem til at skrive koden præcis sådan? ... tjaahhh, hvordan finder lægen ud af præcis hvilken kirtel, den er gal med - og hvordan finder mekanikkeren ud af præcis hvilket print i dit TV, der skal skiftes? Det er deres arbejde ... det er det, de kan  ;o)
Avatar billede olebole Juniormester
20. august 2007 - 14:33 #14
Tak for points  ;o)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Vi tilbyder markedets bedste kurser inden for webudvikling

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester