Как очистить почтовые индексы и ввести данные в MangoDB

import xml.etree.cElementTree as ET
import pprint
import re
import codecs
import json
import os
import string
from pymongo import MongoClient
from collections import defaultdict


#osm data file
cal_data = "hyderabad_india.osm"



#Data Auditing
#Parse through the file with ElementTree and count the number of unique element types to understand overall structure.
def count_tags(filename):
        tags = {}
        for event, elem in ET.iterparse(filename):
            if elem.tag in tags:
                tags[elem.tag] += 1
            else:
                tags[elem.tag] = 1
        return tags
cal_tags = count_tags(cal_data)
pprint.pprint(cal_tags)


#Data Validation
#Using Key_type and process_map we can check weather the keys are valid in mangoDB,and we will check if there are any potential problems.
#Using the function 'key_type', I counted three tags:
#"lower", for tags that contain only lowercase letters,
#"lower_colon", for otherwise valid tags with a colon in their names,
#"problemchars", for tags with problematic characters

lower = re.compile(r'^([a-z]|_)*$')
lower_colon = re.compile(r'^([a-z]|_)*:([a-z]|_)*$')
problemchars = re.compile(r'[=\+/&<>;\'"\?%#$@\,\. \t\r\n]')


def key_type(element, keys):
    if element.tag == "tag":
        for tag in element.iter('tag'):
            k = tag.get('k')
            if lower.search(k):
                keys['lower'] += 1
            elif lower_colon.search(k):
                keys['lower_colon'] += 1
            elif problemchars.search(k):
                keys['problemchars'] += 1
            else:
                keys['other'] += 1
    return keys

def process_map(filename):
    keys = {"lower": 0, "lower_colon": 0, "problemchars": 0, "other": 0}
    for _, element in ET.iterparse(filename):
        keys = key_type(element, keys)

    return keys

cal_keys = process_map(cal_data)
pprint.pprint(cal_keys)



#Problem encountered
#Street Name,Zipcodes

street_type_re = re.compile(r'\b\S+\.?$', re.IGNORECASE)

expected = ["Avenue", "Boulevard", "Commons", "Court", "Drive", "Lane", "Parkway",
                         "Place", "Road", "Square", "Street", "Trail"]

mapping = { "Ct": "Court",
            "St": "Street",
            "st": "Street",
            "St.": "Street",
            "St,": "Street",
            "ST": "Street",
            "street": "Street",
            "Street.": "Street",
            "Ave": "Avenue",
            "Ave.": "Avenue",
            "ave": "Avenue",
            "Rd.": "Road",
            "rd.": "Road",
            "Rd": "Road",
            "Hwy": "Highway",
            "HIghway": "Highway",
            "Pkwy": "Parkway",
            "Pl": "Place",
            "place": "Place"}
def audit_street_type(street_types, street_name):
    m = street_type_re.search(street_name)
    if m:
        street_type = m.group()
        if street_type not in expected:
            street_types[street_type].add(street_name)

def is_street_name(elem):
    return (elem.attrib['k'] == "addr:street")

def audit(osmfile):
    osm_file = open(osmfile, "r")
    street_types = defaultdict(set)
    for event, elem in ET.iterparse(osm_file, events=("start",)):

        if elem.tag == "node" or elem.tag == "way":
            for tag in elem.iter("tag"):
                if is_street_name(tag):
                    audit_street_type(street_types, tag.attrib['v'])

    return street_types
cal_street_types = audit(cal_data)
pprint.pprint(dict(cal_street_types))



#ZIP Codes
def update_name(name, mapping):
    for key in mapping:
        if key in name:
            name = string.replace(name,key,mapping[key])
    return name
def audit_zipcodes(osmfile):
# iter through all zip codes, collect all the zip codes that does not start with 02
        osm_file = open(osmfile, "r")
        zip_codes = {}
        for event, elem in ET.iterparse(osm_file, events=("start",)):
            if elem.tag == "node" or elem.tag == "way":
                    for tag in elem.iter("tag"):
                        if tag.attrib["k"] == "addr:postcode" and not tag.attrib["v"].startswith("50"):
                                if tag.attrib["v"] not in zip_codes:
                                        zip_codes[tag.attrib["v"]] = 1
                                else:
                                        zip_codes[tag.attrib["v"]] += 1
        return zip_codes

zipcodes = audit_zipcodes(cal_data)
for zipcode in zipcodes:
     print zipcode, zipcodes[zipcode]


#Convertion OSM - JSON
#The function to process the XML file, make ready for insert into MongoDB

CREATED = ["version", "changeset", "timestamp", "user", "uid"]

def shape_element(element):
         node = {}
         node["created"] = {}
         node["address"] = {}
         node["pos"] = []
         refs = []
         # we only process the node and way tags
         if element.tag == "node" or element.tag == "way":
             if "id" in element.attrib:
                 node["id"] = element.attrib["id"]
                 node["type"] = element.tag
             if "visible" in element.attrib.keys():
                 node["visible"] = element.attrib["visible"]
                 # the key-value pairs with attributes in the CREATED list are added under key "created"
             for elem in CREATED:
                 if elem in element.attrib:
                     node["created"][elem] = element.attrib[elem]
                     # attributes for latitude and longitude are added to a "pos" array
                     # include latitude value
             if "lat" in element.attrib:
                 node["pos"].append(float(element.attrib["lat"]))
                 # include longitude value
             if "lon" in element.attrib:
                 node["pos"].append(float(element.attrib["lon"]))
                 for tag in element.iter("tag"):
                     if not (problemchars.search(tag.attrib["k"])):
                         if tag.attrib["k"] == "addr:housenumber":
                             node["address"]["housenumber"] = tag.attrib["v"]
                         if tag.attrib["k"] == "addr:postcode":
                             node["address"]["postcode"] = tag.attrib["v"]
                             # handling the street attribute, update incorrect names using the strategy deve
                         if tag.attrib["k"] == "addr:street":
                             node["address"]["street"] = tag.attrib["v"]
                             node["address"]["street"] = update_name(node["address"]["street"], mapping)
                         if tag.attrib["k"].find("addr") == -1:
                             node[tag.attrib["k"]] = tag.attrib["v"]
                 for nd in element.iter("nd"):
                     refs.append(nd.attrib["ref"])
                 if node["address"] == {}:
                     node.pop("address", None)
                 if refs != []:
                     node["node_refs"] = refs
             return node
         else:
             return None


# process the xml openstreetmap file, write a json out file and return a list of dictionaries
def process_map(file_in, pretty=False):
    file_out = "{0}.json".format(file_in)
    data = []
    with codecs.open(file_out, "w") as fo:
             for _, element in ET.iterparse(file_in):
                  el = shape_element(element)
                  if el:
                       data.append(el)
                  if pretty:
                       fo.write(json.dumps(el, indent=2) + "\n")
                  else:
                       fo.write(json.dumps(el) + "\n")
    return data
data = process_map(cal_data, True)

У меня были данные OSM ( OSM_DATA) города - Хайдарабад Я очистил названия улиц, используя сопоставление, но почти удалял удаление почтовых индексов, если они не начинаются с 5 или если они не 6 цифр

и во время выполнения запроса для почтовых индексов. Справка Несколько почтовых индексов имеют название города, как их удалять, передавать данные и генерировать файл.json.

1 ответ

Содержание вашего вопроса сбивает с толку, но из заголовка я получаю общее представление о том, что вы хотите.

Я быстро взглянул на твой код. Я попробовал ссылку на ваши данные, но я не чувствую себя в безопасности при загрузке файлов из общедоступной ссылки на Google Диске, поэтому я не открыл ее.

Я могу сказать, что анализ или проверка адресных данных (например, "очистка почтовых индексов") - сложная задача. Адреса не всегда имеют одинаковый стиль и форму, и люди не вводят адреса стандартным способом. Это приводит к множеству крайних случаев, сложным параметрам сопоставления и путанице при обработке адресных данных. Как правило, не стоит быстро создавать собственный сценарий синтаксического анализа адресов в качестве запоздалой мысли для вашего проекта.

Я рекомендую прочитать больше о стандартизации адресов, проверке адресов и этой статье, сравнивая их.

Поскольку обработка адресных данных часто является важной частью программы и не является легкой частью программы, я рекомендую поискать службу проверки адресов или API, который будет обрабатывать адресные данные для вас. Есть много услуг, доступных услуг.


Полное раскрытие: я работал в SmartyStreets, компании по проверке адресов.

Другие вопросы по тегам