Как очистить почтовые индексы и ввести данные в 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, компании по проверке адресов.