开发者

get city, state or zip from a string in python

I'd like to be able to parse out the city, state or zip from a string in python. So, if I entered

Boul开发者_JAVA百科der, Co

80303

Boulder, Colorado

Boulder, Co 80303

...

any variation of these it would return the city, state or zip.

This is all going to be user inputted data and inputted in one text field.


Just ask for their zip only, then give a (short) list of applicable cities by using a geocode database. That way you get nice clean 5-digit input, they save time, and you all go home happy.

If you already have the data, look just for the zip, find a list of possible cities (there will only be one applicable state) and match for the city name after making everything lowercase.


You could use a geocoding web service or something similar. For example, on the Yahoo geocoding API page, it shows how you can specify the address in a number of ways:

This free field lets users enter any of the following:
    city, state
    city, state, zip
    zip
    street, city, state
    street, city, state, zip
    street, zip

and the XML results provide the parsed address, for example with this test URL specified on the page.


I would use ([^\d]+)?(\d{5})? as my regular expression, and use match so it only matches the beginning of the string. This way it won't fail on bad input and will make its best guess as to what was intended. Then you can split the first capture group on ",".


  1. easy_install ngram

  2. build file with all the city and state names one per line, place in citystate.data Redwood City, CA Redwood, VA etc

  3. Experiment ( the .2 threshold is a little lax )


import string
import ngram
cityStateParser = ngram.NGram(
  items = (line.strip() for line in open('citystate.data')) ,
  N=3, iconv=string.lower, qconv=string.lower,  threshold=.2
)

Example:

cityStateParser.search('redwood')
[('Redwood VA', 0.5),
('Redwood NY', 0.5),
('Redwood MS', 0.5),
('Redwood City CA', 0.36842105263157893),
...
]

Notes: Because these are NGrams you might get overmatch when the state is part of a ngram in the city i.e. search for "washington" would yield Washington IN with a bette score than "Washington OK"

You might also want read Using Superimposed Coding Of N-Gram Lists For Efficient Inexact Matching (PDF Download)


This code seems to do what you want:

text = """
Boulder, Co
80303
Boulder, Colorado
Boulder, Co 80303
"""

lines = text.splitlines()

ABBREV = dict(co="Colorado", ca="California")
STATES = ABBREV.values()

def parse_addr(line):
    addr = {}
    # normalize commas
    parts = line.replace(",", " ").split()
    for part in parts:
        if part.capitalize() in STATES:
            addr["state"] = part
        elif part.lower() in ABBREV:
            addr["state"] = ABBREV[part.lower()]
        else:
            try:
                zip = int(part)
                addr["zip"] = part
            except ValueError:
                addr["city"] = part
    return addr

for line in lines:
    print line, parse_addr(line)

Output:

Boulder, Co {'city': 'Boulder', 'state': 'Colorado'}
80303 {'zip': '80303'}
Boulder, Colorado {'city': 'Boulder', 'state': 'Colorado'}
Boulder, Co 80303 {'city': 'Boulder', 'state': 'Colorado', 'zip': '80303'}

Handling of "South Dakota" and other two-word states/cities left as an exercise for the reader :)

As the other posters suggested, you can get smart and use the zip code to narrow in on the city/state as well.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜