Comment géocoder 300 000 adresses à la volée?

18

J'ai une base de données qui a 300 000 adresses, qui doivent être affichées sur la carte. Je sais que si je géocode toutes les adresses, cela me coûtera trop cher. Je me demandais donc s'il était possible de géocoder l'adresse à la volée / en temps réel, lorsqu'un utilisateur sélectionnerait une adresse (une adresse de propriété), il rechercherait dans la base de données, puis géocoderait l'adresse, puis la cartographierait avec d'autres attributs.

Ce serait vraiment bien si vous pouviez partager un code, un concept ou quoi que ce soit. D'ailleurs mon backend est sur mysql supporté par Joomla.

user1089553
la source
J'utilise généralement la capacité de géocodage d'ArcGIS pour géocoder un grand nombre d'adresses. De plus, je suis vraiment intéressé par les processus expliqués ici, en particulier, comme tester le script python pour géocoder les adresses à l'aide de Google, puis les comparer avec ce que j'ai d'ArcGIS. Malheureusement, il me semble que je ne suis pas en mesure de trouver tous les fichiers et scripts associés qui se trouvent à différents endroits. Il serait tellement apprécié que quelqu'un m'envoie tous les scripts dans un seul fichier zip ou toute instruction étape par étape. J'ai essayé de l'utiliser et d'obtenir des commentaires, mais je n'ai pas réussi
Housh

Réponses:

15

Mehul, je travaillais dans l'industrie de la vérification d'adresse avec une société appelée SmartyStreets. Il existe de nombreux services de géocodage, mais seuls quelques-uns prendront en charge le traitement par lots avec le volume dont vous avez besoin. (Google et d'autres n'autorisent pas l'utilisation en masse de leur API ni le stockage / la mise en cache des résultats.)

Si vous allez dans votre base de données MySQL et effectuez une exportation de votre table qui contient les adresses, enregistrez-la comme fichier CSV par exemple. Vous pouvez ensuite le traiter à l'aide de l' outil Web SmartyList ou de l'outil de ligne de commande . Comme je l'ai dit, il existe plusieurs services, mais vous voudrez quelque chose, je suppose, qui vérifie également l'existence des adresses (d'où la raison du géocodage) - si l'adresse est incorrecte ou incomplète, les résultats du géocodage le sont également . Seuls quelques services le font.

LiveAddress est un service certifié CASS par l'USPS. Il y en a quelques-uns, alors faites vos recherches, mais vous voulez quelque chose "à la volée" / rapide et peu coûteux, je recommande donc LiveAddress. Il vérifiera non seulement l'adresse mais fera ensuite ce que vous souhaitez, à savoir fournir les informations lat / lon et également la précision des résultats de géocodage. Tout est basé sur le Web et traitera des dizaines de millions d'enregistrements en un rien de temps (voir cette question comme référence ).

Si vous avez encore besoin de géocoder des adresses pendant que les utilisateurs interagissent, LiveAddress a également une version d' API qui peut se connecter à peu près n'importe quoi et il prend également en charge le traitement par lots à la volée, mais est payé comme un abonnement, pas une seule fois Paiement.

Mat
la source
Pas familier avec SmartyStreets, semble prometteur, merci pour la tête haute.
Derek Swingley
L'API LiveAddress fera 300 000 en environ 5 à 10 minutes. Le service LiveAddress pour les listes (télécharger une liste pour le traitement) prend 15-20 minutes. Les deux sont assez rapides. Le service de liste ne vous demandera pas d'écrire de code.
Jeffrey
2
SmartyStreets ne géocode que pour les États-Unis?
Mapperz
J'ai des données qui sont pour Singapour ça va marcher? Sinon aucune direction que vous pourriez me donner ????
user1089553
Il existe de nombreuses règles de droit d'auteur avec Google Bing et d'autres fournisseurs. Vous n'exportez pas de données!
11

Si vous aimez Python, vous pouvez utiliser l' API GeoPy , combinée aux liaisons GDAL Python ou Fiona , et créer un script très basique comme celui-ci pour convertir les adresses en un fichier de formes ponctuelles.

Cela géolocalisera un fichier nommé 'addresses_to_geocode', créant un fichier de formes de sortie nommé 'my_output.shp' dans le dossier my_output:

import os
from geopy import geocoders
from osgeo import ogr, osr

def geocode(address):
    g = geocoders.GoogleV3()
    place, (lat, lng) = g.geocode(address)
    print '%s: %.5f, %.5f' % (place, lat, lng)
    return place, lat, lng

def parse_file(filepath, output_shape):
    # create the shapefile
    drv = ogr.GetDriverByName("ESRI Shapefile")
    if os.path.exists(output_shape):
        drv.DeleteDataSource(output_shape)
    ds = drv.CreateDataSource(output_shape)
    # spatial reference
    sr = osr.SpatialReference()
    sr.ImportFromProj4('+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs')
    lyr = ds.CreateLayer(output_shape, sr, ogr.wkbPoint)
    # fields
    featDefn = lyr.GetLayerDefn()
    fld_id = ogr.FieldDefn('id', ogr.OFTInteger)
    fld_address = ogr.FieldDefn('ADDRESS', ogr.OFTString)
    fld_address.SetWidth(255)
    lyr.CreateField(fld_id)
    lyr.CreateField(fld_address)
    print 'Shapefile %s created...' % ds.name
    # read text addresses file
    i = 0
    f = open(filepath, 'r')
    for address in f:
        try:
            print 'Geocoding %s' % address
            place, lat, lng = geocode(address)
            point = ogr.Geometry(ogr.wkbPoint)
            point.SetPoint(0, lng, lat)
            feat = ogr.Feature(lyr.GetLayerDefn())
            feat.SetGeometry(point)
            feat.SetField('id', i)
            feat.SetField('ADDRESS', address)
            lyr.CreateFeature(feat)
            feat.Destroy()
            i = i + 1
        except:
            print 'Error, skipping address...'

parse_file('addresses_to_geocode', 'my_output')

Le fichier est censé avoir juste une ligne pour une seule adresse, comme par exemple:

Via Benedetto Croce 112, Rome, Italy
Via Aristide Leonori 46, Rome, Italy
Viale Marconi 197, Rome, Italy

Ici, j'utilise l'API Google, mais avec GeoPy est très basique pour passer à différentes API, comme Yahoo !, GeoNames ou MapPoint .

capooti
la source
C'est bien! Merci mec! Quoi qu'il en soit, à l'heure actuelle (01/2016), 'geocoders.Google ()' devrait être remplacé par 'geocoders.GoogleV3 ()' comme dans geopy.readthedocs.org/en/1.11.0
umbe1987
1

Une autre option pour résoudre votre problème serait d'importer votre jeu de données dans des tables de fusion et de définir le champ d'adresse comme emplacement. Ensuite, il géocodera automatiquement les points. Une fois cela terminé, vous pouvez exporter les données au format KML.

Ou..alternativement, vous pouvez écrire un script php pour utiliser le géocodeur yahoo qui a une limite de 50 000 enregistrements, donc tôt ou tard vous aurez tous vos points géocodés dans votre base de données.

J'espère que cela a aidé!

EZMapdesign
la source
merci tamas mais je ne voudrais pas obtenir le kml, puis récupérer les informations à partir de là, puis mdb. J'aime l'idée du géocodage yahoo mais je ne suis pas trop sûr de sa précision, car je n'ai jamais utilisé yahoo pour la cartographie. Veuillez me faire savoir si vous avez un script écrit ou quelque chose. Ceci est d'une grande aide
user1089553
Gardez à l'esprit que l'utilisation de géocodeur Yahoo (ou Google, d'ailleurs) avec des requêtes automatisées ou sans afficher une carte violera les TOS ...
Matt
Pour autant que je sache, ce n'est pas si vous présentez la sortie sur une carte. Corrigez-moi si je me trompe!
EZMapdesign
@Tamas Type de. Voir cependant ceci: developers.google.com/maps/terms#section_10_1_3
Matt
0

Ce n'est peut-être pas la meilleure réponse à votre question, mais vous pouvez essayer BatchGeo. La version gratuite vous ferait beaucoup souffrir, mais c'était quand même assez bien pour mon travail. Cependant, nous avons acheté la version pro.

L'astuce pour obtenir les coordonnées du fichier KML consiste à l'importer dans ArcGIS ultérieurement.

Anıl Çelik
la source
Merci, pouvez-vous me dire comment faire un BatchGeo, connaissez-vous également les noms de la version gratuite (j'essayais pour Google Map api v3). Cela signifie-t-il également que je dois stocker les valeurs Lat / Long dans ma base de données afin de les mapper. C'est ce que j'avais l'intention de faire en premier lieu.
user1089553
Avec BatchGeo, vous devrez importer du KML dans votre base de données puis extraire les coordonnées, je ne connais pas d'autre moyen car Google interdit de fournir des coordonnées. À propos de Yahoo, mon expérience avec la Turquie n'est pas vraiment brillante. La plupart des pays en développement sont exclus du champ d'application de Yahoo. Anil.
Anıl Çelik
0

J'ai utilisé avec succès geopy qui utilise le service Web de géocodage de Google. Il fonctionne parfaitement jusqu'à 2 000 points par 24 heures.

Matej
la source
0

Matej, c'est parce que l'API Google permet de tirer jusqu'à 2,5k par jour.
À propos de la solution Geo, le traitement par lots n'est pas encore trouvé, c'est parce que d'après mon examen du code geo python, il semble qu'il ouvre une connexion chaque fois qu'il demande un nouveau cordinate, 300k restera probablement bloqué pour toujours (probablement avec l'erreur 400).
Jouer avec des Poligons devrait faire l'affaire, mais cela dépend de votre zone de jeu, que ce soit 1 pays ou n pays.
Pour 1 pays, les polygones devraient fonctionner plutôt bien.
Pour n pays, la solution ne fonctionnera pas car la collecte prendra plus de temps chaque fois que vous ajoutez un autre pays. La meilleure approche pour le faire est une charge paresseuse.
=> commencez avec l'idée du polygone, tout dans un autre pays, créez une grande table de base de données pour contenir les données, vous finirez par contenir les données dont vous avez besoin, je suppose.

Benjaminel
la source
0

Si vous voulez le faire avec PHP - MySQL, voici une solution qui a fonctionné pour moi:

<script type="text/javascript" charset="utf-8">

    var customIcons = {
      restaurant: {
        icon: 'http://labs.google.com/ridefinder/images/mm_20_blue.png',
        shadow: 'http://labs.google.com/ridefinder/images/mm_20_shadow.png'
      },
      bar: {
        icon: 'http://labs.google.com/ridefinder/images/mm_20_red.png',
        shadow: 'http://labs.google.com/ridefinder/images/mm_20_shadow.png'
      },
      club:
      {
        icon: 'http://labs.google.com/ridefinder/images/mm_20_yellow.png',
        shadow: 'http://labs.google.com/ridefinder/images/mm_20_shadow.png' 
      },
      church:
      {
        icon: 'http://labs.google.com/ridefinder/images/mm_20_green.png',
        shadow: 'http://labs.google.com/ridefinder/images/mm_20_shadow.png' 
      }
    };

      function initialize() 
      {
        var mapOptions = {
          center: new google.maps.LatLng(37.976178, 23.735881),
          zoom: 7,
          mapTypeId: google.maps.MapTypeId.roadmap
        };
        var map = new google.maps.Map(document.getElementById("map-canvas"),
            mapOptions);
        <?php header("content-type: text/html;charset=utf-8");
        $getpoints = "SELECT lat, lng, name, address, type FROM markers";
        $getpoints .= $filter;

        if(!$result = $con->query($getpoints)){
        die('There was an error running the query 
        [' . $con->error . ']');
        }

        else 
        {
            while ($row = $result->fetch_assoc()) 
            {
                $thematic = "'$row[type]'";
                $name = "'$row[name]'";
                $map_address = "$row[address]";

                $url = "http://maps.googleapis.com/maps/api/geocode/json?sensor=false&address=".urlencode($map_address);
                $lat_long = get_object_vars(json_decode(file_get_contents($url)));

                // pick out what we need (lat,lng)
                $lat_long = $lat_long['results'][0]->geometry->location->lat . "," . $lat_long['results'][0]->geometry->location->lng;

                echo "var myLatlng1 = new google.maps.LatLng($lat_long); 
                var icon = customIcons[$thematic] || {};
                var marker1 = new google.maps.Marker({ 
                position: myLatlng1, 
                map: map,
                icon: icon.icon,
                title: '$map_address'
                });";           
            }
        }       

        ?>    
      }

      google.maps.event.addDomListener(window, 'load', initialize);
    </script>
pancy1
la source
0

Essayez cette API de géocodage . C'est gratuit pour une petite utilisation mais si vous en voulez plus, ils vous font payer. C'est bon marché cependant et vous pouvez traiter cela très facilement, j'en traite des millions par mois.

John M.
la source
0

Vous pouvez enregistrer vos données dans un fichier texte (un enregistrement par ligne) puis les géocoder par lots à l'aide de ce service: http://geocode.xyz/batch (fonctionne pour la plupart des pays européens)

ou, vous pouvez écrire votre propre code pour accéder à l'API REST / JSON: http://geocode.xyz/api (c'est gratuit pour des recherches illimitées)

Ervin Ruci
la source
0

Utilisez les outils de mappage (Pointage de carte | Outil de géocodage par lots ( http://www.mappointing.com/ )) Dans cet outil, vous pouvez traiter les données à l'aide de la clé API gratuite de Google Map. Et cet outil fournit également un outil de calcul de distance et de recherche de lieu.

Debasis Sahu
la source
Pourquoi cela n'atteindrait-il pas la même limite API que OP mentionnée?
lynxlynxlynx