我正在尝试创建一个正则表达式来将地址解析为五个部分: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”作为输入,同样的结果。
答案 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