如何动态对30万个地址进行地址解析?


18

我有一个数据库,该数据库有300,000个地址,将在地图上显示。我知道如果我对所有地址都进行地理编码,那对我来说太昂贵了。所以我想知道是否可以实时/实时地对地址进行地理编码,当用户选择一个地址(属性地址)时,它将搜索数据库,然后对该地址进行地理编码,然后使用其他属性。

如果您可以共享代码,概念或任何内容,那将是非常不错的。顺便说一下,我的后端在Joomla支持的mysql上。


我通常使用ArcGIS地理编码功能对大量地址进行地理编码。另外,我对这里介绍的过程特别感兴趣,例如,测试python脚本以使用Google对地址进行地理编码,然后将其与我从ArcGIS获得的地址进行比较。不幸的是,在我看来,我找不到在不同位置的所有相关文件和脚本。如果有人将所有脚本发送给我一个zip文件或任何分步说明,将非常感谢。我尝试使用它并收到一些反馈,但我没有成功
Housh13年

Answers:


15

Mehul,我曾经在一家名为SmartyStreets的公司从事地址验证行业的工作。那里有很多地理编码服务,但是只有少数将支持所需数量的批处理。(Google和其他公司不允许大量使用其API或存储/缓存结果。)

如果您转到MySQL数据库并执行包含地址的表的导出,则将其另存为CSV文件。然后,您可以使用SmartyList Web工具命令行工具对其进行处理。就像我说的那样,那里有几种服务,但是我想您还需要一些可以验证地址是否存在的地址(因此进行地址解析)-如果地址错误或不完整,则地址解析结果也是如此。只有少数服务可以做到这一点。

LiveAddress是一项由USPS 认可CASS服务。您可以进行一些研究,但是您需要“即时” /快速且便宜的东西,因此我再次推荐LiveAddress。它不仅会验证地址,而且会根据您的要求进行操作(提供经纬度信息)以及地理编码结果的精度。都是基于Web的,将立即处理数千万条记录(请参阅此问题作为参考)。

如果您在用户交互时进一步需要对地址进行地理编码,则LiveAddress还具有一个API版本,可以插入几乎所有内容,并且还支持即时批处理,但是是作为订阅而非一次性支付的付款。


对SmartyStreets不熟悉,看起来很有希望,感谢大家的注意。
Derek Swingley,2012年

LiveAddress API将在大约5-10分钟内完成300,000个操作。LiveAddress for Lists服务(上载列表进行处理)需要15到20分钟。两者都非常快。列表服务将不需要您编写任何代码。
Jeffrey 2012年

2
SmartyStreets仅适用于美国的地理编码吗?
Mapperz

我有适合新加坡使用的数据吗?如果没有任何指示,您可以给我吗?
user1089553 2012年

Google Bing和其他提供商使用许多版权规则。您不导出数据!

11

如果您喜欢Python,可以使用 GeoPy APIGDAL Python绑定Fiona结合使用,并创建一个像这样的非常基本的脚本,用于将地址转换为点shapefile。

这将对名为“ addresses_to_geocode”的文件进行地理定位,在my_output文件夹中创建一个名为“ my_output.shp”的输出shapefile:

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')

该文件应该仅在一行中包含一个地址,例如:

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

在这里,我使用的是Google API,但使用GeoPy切换到其他API(例如Yahoo!,GeoNames或MapPoint)非常基础


这很棒!谢啦!无论如何,目前(2016
umbe1987年

1

解决您的问题的另一种方法是将数据集导入融合表,并将地址字段设置为位置。然后它将自动对点进行地理编码。完成后,您可以将数据导出为KML。

或者..或者,您可以编写一个php脚本来使用yahoo地理编码器,该编码限制为5万条记录,因此迟早您将在数据库中对所有点进行地理编码。

希望对您有所帮助!


谢谢tamas,但我不想获取kml,然后从那里获取信息,然后再发送到m db。我确实喜欢yahoo地理编码的想法,但是我不太确定它的准确性,因为我从未使用过yahoo进行映射。如果您编写了任何脚本或其他东西,请告诉我。这是一个很大的帮助
user1089553 2012年

请记住,在自动查询中使用Yahoo(或Google)地理编码器或不显示地图将违反TOS ...
Matt

据我所知,不是在地图上显示输出。如果我错了,请纠正我!
EZMapdesign 2012年

@Tamas有点。但是,请参见以下内容:developers.google.com/maps/terms#section_10_1_3
马特2012年


0

也许不是您问题的最佳答案,但您可以尝试BatchGeo。免费版本会让您遭受很多折磨,但对于我的工作来说仍然足够。不过,我们已经购买了专业版。

从KML文件获取坐标的技巧是稍后将其导入到ArcGIS。


谢谢,您能告诉我我该怎么做BatchGeo,您是否也知道免费版本的名称(我正在尝试使用Google Map api v3)。这是否还意味着我必须将纬度/经度值存储在数据库中才能进行映射。这是我首先要做的。
user1089553 2012年

使用BatchGeo,您必须将KML导入数据库,然后提取坐标,我知道没有其他方法,因为Google禁止提供坐标。关于雅虎,我在土耳其的经历并不十分光明。大多数发展中国家被排除在雅虎的范围之外。阿尼尔
阿尼尔·切利克

0

我已经成功使用了使用Google地理编码网络服务的geopy。每24小时最多可达到2k点。


0

Matej,那是因为Google API每天最多可以拉2千5百万。
关于Geo解决方案,尚未发现支持批处理,这是因为从我对geo python代码的审查来看,每次他请求新坐标时似乎都打开了连接,因此300k可能会永远卡住(可能出现错误400)。
与Poligons玩应该可以解决问题,但这取决于您的“游戏场地”区域是1个国家还是n个国家。
对于1个国家/地区,多边形应该可以正常工作。
对于n个国家/地区,该解决方案将无法正常工作,因为您每次添加其他国家/地区都会花费更长的时间。最好的方法是延迟加载。
=>从多边形的想法开始,在另一个国家的每件事,创建一个大数据库表来保存数据,最终您将保存我想要的数据。


0

如果您想使用PHP-MySQL,请使用以下解决方案:

<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>

0

试试这个地理编码api。少量使用是免费的,但是如果您想要更多,则可以付费。但是它很便宜,您可以轻松地进行处理,我每个月要处理数百万人。


0

您可以将数据另存为文本文件(每行一条记录),然后使用以下服务对其进行批处理地理编码:http : //geocode.xyz/batch(适用于大多数欧洲国家/地区)

或者,您可以编写自己的代码来访问REST / JSON API:http : //geocode.xyz/api (无限制查找是免费的)


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.