从字符串中解析出可用的街道地址、城市、州和邮政编码

133

问题:我有一个来自Access数据库的地址字段,已转换为SQL Server 2005。这个字段将所有内容都放在一个字段中。我需要将地址的各个部分解析成其规范化表中相应的字段。我需要对大约4,000条记录执行此操作,并且需要可重复。

假设:

  1. 暂时假设地址位于美国

  2. 假设输入字符串有时会包含被寄信人(收件人)和/或第二个街道地址(即B套房)

  3. 州名可能会缩写

  4. 邮政编码可能是标准的5位数字或zip+4

  5. 有些情况下可能存在拼写错误

更新:回答的问题后,标准并不是普遍适用的;我需要存储单独的值,而不仅仅是地理编码和errors表示拼写错误(已更正)

示例数据:

  • A. P. Croll & Son 2299 Lewes-Georgetown Hwy, Georgetown, DE 19947

  • 11522 Shawnee Road, Greenwood DE 19950

  • 144 Kings Highway, S.W. Dover, DE 19901

  • Intergrated Const. Services 2 Penns Way Suite 405 New Castle, DE 19720

  • Humes Realty 33 Bridle Ridge Court, Lewes, DE 19958

  • Nichols Excavation 2742 Pulaski Hwy Newark, DE 19711

  • 2284 Bryn Zion Road, Smyrna, DE 19904

  • VEI Dover Crossroads, LLC 1500 Serpentine Road, Suite 100 Baltimore MD 21

  • 580 North Dupont Highway Dover, DE 19901

  • P.O. Box 778 Dover, DE 19903


几个问题:
  1. 有任何分隔符吗?
  2. 字符串中的字段顺序是什么?
  3. 在数据错误的情况下,您希望出现什么行为(例如将地址推入SQL表中的单个字段,其他字段留空)?
- Jay Mooney
好问题,非常有趣的答案。从邮编倒推似乎是一个常见的主题,但如果你从客户那里获取原始数据,邮编可能不准确。我猜大多数网站例如90210都有不成比例的地址数量。 - Kevin Williams
4
@Kevin:是的,因为你们美国人喜欢用“邮政编码”来锁住我们加拿大人,不接受我们的邮政编码,从而迫使我们输入一些无意义的内容来绕过系统...不幸的是,我唯一知道的邮编是90210 :-) 编辑:算了吧...你显然和我在不远处的卑诗省住得很近。那么你可能也会做同样的事情 :-P - mpen
2
请参考这个 Stack Overflow 问题以获取更详细的概述。 - Matt
24个回答

6
有没有任何标准来记录地址呢?例如:
1. 街道1、街道2、城市、州和邮编之间是否总是用逗号或换行符分隔? 2. 地址类型(路、街道、林荫大道等)是否总是拼写完整?总是缩写吗?两者都有? 3. 定义“错误”。
我的一般答案是一系列正则表达式,但这取决于答案的复杂程度。如果根本没有一致性,那么您可能只能通过正则表达式实现部分成功(即:过滤邮政编码和州),并且必须手动完成其余部分(或至少仔细检查其余部分以确保发现错误)。

6

另一个请求示例数据。

如之前所提到的,我会从邮政编码开始逆向工作。

一旦您有了邮政编码,我会查询一个邮政编码数据库、存储结果并将其和邮政编码从字符串中删除。

这将留下地址的混乱。大多数(全部?)地址都以数字开头,因此找到剩余字符串中第一次出现数字的位置,并从该位置到字符串(新)结尾获取所有内容。那就是你的地址。任何在该数字左边的东西可能都是收件人地址。

现在,您应该已经在表中存储了城市、州和邮政编码,可能还有两个字符串,收件人和地址。对于地址,请检查是否存在"Sute"或"Apt."等,并将其拆分为两个值(地址行1和2)。

对于收件人,我建议获取该字符串的最后一个单词作为姓氏,并将其余部分放入名字字段中。如果您不想这样做,您需要检查称谓(Mr.、Ms.、Dr.等)是否在开头,并根据空格数量做出一些假设,以确定姓名组成方式。

我认为没有任何方法可以百分百准确地解析。


5

基于样本数据:

  1. 我会从字符串的结尾开始。解析邮政编码(任何一种格式)。从最后一个空格向前读取。如果没有找到邮政编码,则出现错误。

  2. 然后去掉末尾的空格和特殊字符(逗号)。

  3. 接着处理州名,同样使用空格作为分隔符。可以使用查找表来验证两个字母的州代码和完整的州名。如果没有找到有效的州,则出现错误。

  4. 再次去掉末尾的空格和逗号。

  5. 城市名称比较棘手,我会在这里使用逗号,有可能会获得太多的城市数据。查找逗号或行首。

  6. 如果字符串中仍有字符剩余,则将所有这些字符放入地址字段中。

这并不完美,但应该是一个相当不错的起点。


4
如果是人工输入的数据,你将花费太多时间来编写代码来处理异常情况。
尝试以下方法:
  1. 使用正则表达式提取邮政编码

  2. 通过适当的政府数据库进行邮政编码查找,以获取正确的地址

  3. 让实习生手动验证新数据与旧数据是否匹配


3

RecogniContact似乎对公众关闭了。访问需要提交联系表格,但却没有回复。也许有其他人知道如何联系他们。 - Luke Van In

3
这不会解决你的问题,但如果你只需要这些地址的经纬度数据,Google Maps API可以相当好地解析非格式化的地址。

3

3
这种问题很难解决,因为数据中存在潜在的歧义。
这里提供基于Perl的解决方案,它使用正则表达式定义递归下降语法树来解析许多有效的街道地址组合:http://search.cpan.org/~kimryan/Lingua-EN-AddressParse-1.20/lib/Lingua/EN/AddressParse.pm。这包括地址内部的子属性,如: 12 1st Avenue N Suite#2 Somewhere CA 12345 USA
它类似于上面提到的http://search.cpan.org/~timb/Geo-StreetAddress-US-1.03/US.pm,但也适用于非美国的地址,例如英国、澳大利亚和加拿大。
这是您样例地址的输出结果。请注意,需要先从“A. P. Croll & Son 2299 Lewes-Georgetown Hwy, Georgetown, DE 19947”中删除名称部分,以将其缩减为“2299 Lewes-Georgetown Hwy, Georgetown, DE 19947”。只需删除字符串中找到的第一个数字之前的所有数据即可轻松实现此操作。
Non matching part       ''
Error                   '0'
Error descriptions      ''
Case all                '2299 Lewes-Georgetown Hwy Georgetown DE 19947'
COMPONENTS              ''
country                 ''
po_box_type             ''
post_box                ''
post_code               '19947'
pre_cursor              ''
property_identifier     '2299'
property_name           ''
road_box                ''
street                  'Lewes-Georgetown'
street_direction        ''
street_type             'Hwy'
sub_property_identifier ''
subcountry              'DE'
suburb                  'Georgetown'

2

使用谷歌API

$d=str_replace(" ", "+", $address_url);
$completeurl ="http://maps.googleapis.com/maps/api/geocode/xml?address=".$d."&sensor=true"; 
$phpobject = simplexml_load_file($completeurl);
print_r($phpobject);

1
这可能违反了服务条款,但看起来应该可以工作 - 尽管重新阅读问题,它并不完全符合要求。 - Jamie Bull

2

由于单词存在错误的可能性,考虑使用SOUNDEX与LCS算法相结合来比较字符串,这将有很大帮助!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接