如何将地址解析为其各个组件

本文关键字:组件 地址解析 | 更新日期: 2023-09-27 18:00:05

我的任务是构建一个解析器来解析特定的网页,以便我们的员工可以将他们的用户数据批量导入到我们公司的网站上。

我已经利用 HtmlAgilityPack 来解析页面,我已经将要推送到Map类中的属性中的table rowtable data相关联。

然而,有一让我感到非常悲伤。 地址列是我身边的眼中钉,原因有很多。

示例数据:

6313 SW 203rd Ave <br> Portland, OR 97224
16600 Lomita Way <br> El Dorado Hills, CA 95762
PO Box #42 <br> Hampton Bays, NY 11946
这些地址

中的每一个都是这样包装的(显然,这些地址可能会因我们为其导入用户的客户而异(:

<tr>
     <td> 6313 SW 203rd Ave <br> Portland, OR 97224 </td>
</tr>

我正在尝试实现一个正则表达式以将其拆分到适当的区域,因此可以将其分配给相关属性:

public string Unit { get; set; }
public string Street { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Zip { get; set; }

但是,这些地址并没有提供太多锚定:

问题一:如果我锚定在<br>,那么我只是分开了线条。 未完全拆分为适当的段。

问题二:单个逗号也有同样的问题。

问题三:如果我锚定为数值,因为 Zip 可能对加拿大无效,并且可能会根据街道名称错误地拆分。

分隔地址项目的最佳方法是什么?用正则表达式?

如何将地址解析为其各个组件

解析地址很难;真的很难。地址没有真正统一的格式,尤其是跨国界地址。您极不可能使用单个正则表达式来做到这一点。

请参阅另一篇文章以获取一些示例和更深入的解释。如何将自由格式的街道/邮政地址从文本中解析为组件

使用正则表达式可以执行的操作是有限制的,但是这里有一个示例,假设您的地址始终遵循此格式。如果您无法确保您的地址遵循特定格式(由您的域强制执行(,您将不得不依赖一些更复杂的解决方案,例如另一个答案中讨论的内容。

另请查看从字符串中解析可用的街道地址、城市、州、邮政编码

编辑:对不起,我忘记这是一个C#问题...但你明白了。

var parseAddress = (function (rx) {
  return function parseAddress(html) { 
      var matches = html.match(rx);
      return {
          unit: matches[1],
          street: matches[2],
          city: matches[3],
          state: matches[4],
          zip: matches[5]
      };
  };
})(/^('d*)'s*(.+?)'s*<br>'s*(.+?),'s*(.+?)'s*('d+)$/);
parseAddress('6313 SW 203rd Ave <br> Portland, OR 97224');
//Object {unit: "6313", street: "SW 203rd Ave", city: "Portland", state: "OR", zip: "97224"}

好的,所以Address字段解析起来非常痛苦。 但是,我确实设法根据我的特定要求解析了数据。

  • Address总是在街道和城市之间有一条<br>

所以我做了以下工作:

var splitBasedOnHTML = Regex.Split(column[2], @"'br<br>");

column[]包含我在index two的地址。 因此,在该调用之后,它将自动将我的单元和街道定位在Index Zero中。 城市、州和邮政编码将位于Index One

所以我又做了一次拆分,像这样打破城市、州和 Zip:

var splitBasedOnSpace = splitBasedOnHtml[1].Split(' ');

之后,我现在得到以下内容:

6313 SW 203rd Ave // splitBasedOnHtml[0]
Portland, // splitBasedonSpace[0]
OR // splitBasedOnSpace[1]
97224 // splitBasedOnSpace[2]

所以我只是将我的属性映射到那些单独的数组索引。

这种解决方案假定该股与街道分开,这成为一个可以的牺牲,因为数据被导入到另一个网站,以后可以由特定的人修改。

这就是我解决解析问题的方式,这个解决方案可能对这艘船上的其他人不可行,但希望这是一个很好的选择或指向一个好的方向。 该方法如下所示:

    public static Map AddressMapper(IList<string> column)
    {
        var map = new Map();
        var splitBasedOnHTML = Regex.Split(column[2], @"'b<br>");
        var splitBasedOnSpace = splitBasedOnHTML[1].Split(' ');
        map.Street = splitBasedOnHTML[0];
        map.City = splitBasedOnSpace[0].Replace(@",", " ");
        map.State = splitBasedOnSpace[1];
        map.Zip = spliteBasedOnSpace[2];
        return map;
    }

如果你去掉了html标签,那么强大的开源库libposting非常适合这个用例。存在与不同编程语言的绑定。Libpostal 是一个 C 库,用于使用统计 NLP 和开放数据解析/规范化世界各地的街道地址。该项目的目标是理解每种语言中基于位置的字符串,无处不在。

我已经创建了一个带有 Python 绑定 pypostal 的简单 Docker 映像,您可以分拆并非常轻松地尝试 pypostal-docker