【问题标题】:Normalizing street addresses in Django/Python在 Django/Python 中规范化街道地址
【发布时间】:2011-06-17 19:39:35
【问题描述】:

我有一个 Django 表单,其中一个字段是街道地址的 TextInput

我想规范化数据。例如:

>> normalize('420 East 24th St.')
'420 E. 24th Street'

>> normalize('221 Amsterdam Av')
'221 Amsterdam Ave.'

>> normalize('221 Amsterdam Avenue')
'221 Amsterdam Ave.'

或者类似的东西。我已经在使用geopy 进行地理编码。也许这可能会有所帮助?

另外:我应该在哪里标准化?在数据库模型中还是在表单域的clean函数中?

【问题讨论】:

  • 对不起:美国。特别是纽约市。

标签: python django django-models django-forms geopy


【解决方案1】:

最可靠的方法是使用真实地址验证服务。它不仅会根据 USPS 标准(参见 Publication 28)对地址组件进行标准化(规范化),而且您还将确定地址是真实的。

完全披露:我在 SmartyStreets 工作,它提供了这样一个 service。下面是一些非常简单的 Python 示例代码,展示了如何通过 HTTP GET 请求使用我们的服务:

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

【讨论】:

  • 我正在开发一个必须处理地址的库,虽然 SmartyStreets 看起来有点贵(尽管免费层相当慷慨),并且可能会给我的库增加一点延迟(需要往返服务器),它看起来是一项非常棒的服务。我想我可能会增加对它的支持。 继续努力!
  • 谢谢!请注意,我们是地理分布的,请求在离用户位置最近的数据中心处理,从而减少了延迟。
【解决方案2】:

这就是我最终解决这个问题的方式(不是双关语):

### models.py ###

def normalize_address_for_display(address):

    display_address = string.capwords(address)

    # Normalize Avenue
    display_address = re.sub(r'\b(Avenue|Ave.)\b', 'Ave', display_address)

    # Normalize Street
    display_address = re.sub(r'\b(Street|St.)\b', 'St', display_address)

    # ...and other rules...

    return display_address

class Store(models.Model):

    name = models.CharField(max_length=32)
    address = models.CharField(max_length=64)
    city = models.CharField(max_length=32)
    state = models.CharField(max_length=2)
    zipcode = models.CharField(max_length=5)

    @property
    def display_address(self):
        return normalize_address_for_display(self.address)

然后我在模板中使用Place.display_address。这使我可以将原始用户提交的数据保留在数据库中而无需修改,并且在我想要标准化显示版本时只使用display_address

欢迎 cmets/建议。

【讨论】:

  • 注意最后一个\b 如果后面没有新单词字符,则不会匹配。请改用r'\b(?:Street\b|St\.\B)'regex101.com/r/aeuAbj/1
【解决方案3】:

我最近创建了一个street-address python 模块,它的 StreetAddressFormatter 可以用来规范你的地址。

【讨论】:

    【解决方案4】:

    一种选择是使用 Geopy 在 Yahoo 或 Google Maps 之类的人上查找地址,然后返回与其匹配的地址的完整地址。您可能需要注意返回地址中的公寓号码是否被截断(例如,“221 Amsterdam Av #330”变为“221 AMSTERDAM AVENUE”)。此外,您还将获得城市/州/国家/地区信息,用户可能还会缩写或拼写错误。

    如果有多个匹配项,您可以提示用户反馈哪个是他们的地址。在不匹配的情况下,您还可以让用户知道,并可能允许保存地址,具体取决于有效地址的重要性以及您对地址查找提供者有效性的信任程度。

    关于在表单与模型中进行这种规范化,我不知道首选的 Django 做事方式是什么,但我的偏好是在表单中,例如:

    def clean(self):
        # check address via some self-defined helper function
        matches = my_helper_address_matcher(address, city, state, zip)
        if not matches:
            raise forms.ValidationError("Your address couldn't be found...")
        elif len(matches) > 1:
            # add javascript into error so the user can select 
            # the address that matches? maybe there is a cleaner way to do this
            raise forms.ValidationError('Did you mean...') 
    

    你可以在模型(或一些 helpers.py 文件)中加入这个查找函数,以防你想在其他领域重用它

    【讨论】:

    • 请注意,我使用过这些服务,但它们并不是非常准确,尤其是公寓和分区。此外,即使不是不可能,它们也很难用于处理大批量。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-11
    • 1970-01-01
    相关资源
    最近更新 更多