正则表达式匹配地址与子模式

时间:2011-09-07 14:18:55

标签: python regex

我正在尝试创建一个正则表达式来将地址解析为五个部分:address1,即街道地址,address2,即公寓号码或地址,城市,州的第2行上显示的任何其他内容和邮政编码。

当我运行它时,python(或Django)抛出一个错误,当我运行re.search时,该错误指出“模式的意外结束”。谁能告诉我如何修改这个正则表达式才能正确匹配?

我是一个正常的表达菜鸟。我可以弄清楚这个应该做的大部分内容,但我自己也写不出来。我是从http://regexlib.com/REDetails.aspx?regexp_id=472得到的。

re.compile(r"""
(?x)^(?n:
(?<address1>
    (\d{1,5}(\ 1\/[234])?(\x20[A-Z]([a-z])+)+ )
    | (P.O. Box \d{1,5}))\s{1,2}
(?<city>
    [A-Z]([a-z]) 
        + (\.?)(\x20[A-Z]([a-z])+){0, 2})\, \x20
(?<state>
    A[LKSZRAP] | C[AOT] | D[EC] | F[LM] | G[AU] | HI
    | I[ADL N] | K[SY] | LA | M[ADEHINOPST] | N[CDEHJMVY]
    | O[HKR] | P[ARW] | RI | S[CD] | T[NX] | UT | V[AIT] 
    | W[AIVY] 
    | [A-Z]([a-z])
        + (\.?)(\x20[A-Z]([a-z])+){0,2})\x20
(?<zipcode>
    (?!0{5})\d{5}(-\d {4})?)
)$"
""", re.VERBOSE)

为了便于阅读,添加了新行。作为一个后续问题,为了便于阅读,可以将这个正则表达式分成多行,或者它是否需要全部在一行中才能工作(我想可以连接单独的行,我猜)。

P.S。我知道这有点像家庭作业,但它实际上是为了工作。

编辑:请求使用的实际代码,所以在这里。我把它遗弃了,因为这里的所有东西实际上已经存在了,但也许它会有所帮助。

该函数是Django视图的一部分,但这对我们的目的而言并不重要。

def parseAddress(address):
  pattern = r"^(?n:(?<address1>(\d{1,5}(\ 1\/[234])?(\x20[A-Z]([a-z])+)+ )|(P\.O\.\ Box\ \d{1,5}))\s{1,2}(?i:(?<address2>(((APT|APARTMENT|BLDG|BUILDING|DEPT|DEPARTMENT|FL|FLOOR|HNGR|HANGER|LOT|PIER|RM|ROOM|S(LIP|PC|T(E|OP))|TRLR|TRAILER|UNIT)\x20\w{1,5})|(BSMT|BASEMENT|FRNT|FRONT|LBBY|LOBBY|LOWR|LOWER|OFC|OFFICE|PH|REAR|SIDE|UPPR|UPPER)\.?)\s{1,2})?)(?<city>[A-Z]([a-z])+(\.?)(\x20[A-Z]([a-z])+){0,2})\, \x20(?<state>A[LKSZRAP]|C[AOT]|D[EC]|F[LM]|G[AU]|HI|I[ADL N]|K[SY]|LA|M[ADEHINOPST]|N[CDEHJMVY]|O[HKR]|P[ARW]|RI|S[CD] |T[NX]|UT|V[AIT]|W[AIVY]|[A-Z]([a-z])+(\.?)(\x20[A-Z]([a-z])+){0,2})\x20(?<zipcode>(?!0{5})\d{5}(-\d {4})?))$"
  match = re.search(pattern, address)

我使用我的家庭住址作为输入,但我尝试了“123 Main St.,Austin,TX 12345”作为输入,同样的结果。

5 个答案:

答案 0 :(得分:4)

有些人可能不会认为这是一个答案,但请耐心等待一分钟。

我强烈建议尝试使用正则表达式解析街道地址。街道地址在任何意义上都不是“常规”的。有无限的变化,除非你将自己局限于非常有限的语法,否则总会有你无法解析的字符串。从美国邮政局和许多众多列表清理服务提供商开始,已经投入大量时间和金钱来解析解析地址的解决方案。只需Google“解析街道地址”即可获得问题范围的提示。有商业解决方案和一些免费的解决方案,但网上的评论表明,没有人能够一直做到正确。

我也是从经验中说出来的。在80年代,我在一家数据库排版公司工作,我们不得不解析地址。我们从未能够开发出完美的解决方案,而且对于我们自己捕获的数据(我们有一个大型键盘部门),我们开发了一种特殊的符号语法,因此操作员可以在适当的位置插入分隔符以帮助解析过程。

看看那里的一些免费服务。你会省去很多麻烦。

答案 1 :(得分:2)

在正则表达式中设置x(详细)标记,即:(?x)

答案 2 :(得分:1)

一个非正则表达式的答案:查看python库usaddress(还有一个web interface用于尝试它)

同意Jim的说法,正则表达式不是一个好的解决方案。 usaddress以概率方式解析地址,并且在处理凌乱的地址时比基于正则表达式的解析器更强大

答案 3 :(得分:0)

您的正则表达式在第一个字符n上失败,您可以按如下方式进行验证。创建一个文件test.py并输入以下内容:

 import re
 re.compile(r'...')

当然你填写你的模式:)现在运行python -m pdb test.py,输入c继续,它会在引发异常时停止。在那时,键入l以查看代码中的位置。您看到它失败,因为source.next不在FLAGS中。此source只是您的模式,因此您可以通过键入print source.index来验证失败的位置。

此外,删除前面的n,模式在a的第一个<address1>处失败。

(?n很奇怪,我在文档中找不到它,所以它似乎是一个不受支持的扩展名。至于?<address1>,我认为这应该是?P<address1>。还有更多问题,例如(?i:,如果我删除它们并修复?P<内容,我会在最后一个括号中出现关于不平衡括号的错误。

答案 4 :(得分:0)

Jim Garrison(上图)是正确的 - 地址太多了,不能用正则表达式解析。我在一家地址验证软件公司工作 - SmartyStreets。试试我们的LiveAddress API - REST端点提供了一个很好的,易于使用的JSON响应中解析的所有地址组件。这是一个示例:

https://github.com/smartystreets/LiveAddressSamples/blob/master/python/street-address.py