OpenGeoDB PLZ-TSV-Dateien mit Python parsen

English Deutsch

Problem:

Du möchtest die OpenGeoDB Postleitzahl-TSV-Dateien parsen, die hier verfügbar sind.

Lösung

Je nach Anwendungsfall könnte PyGeoDB, das auf den OpenGeoDB-Online-Dienst zugreift, eine besser geeignete Lösung sein.

Wenn du eine lokale Lösung für deine Aufgabe benötigst, ist hier ein einfaches Python-Skript im Generator-Stil, das die Informationen in einem namedtuple speichert. Es enthält ein Beispiel.

parse_opengeodb_plz.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Ein OpenGeoDB PLZ-TSV-Parser

Dieser Parser kann verwendet werden, um TSV-Dateien zu parsen, die unter
https://web.archive.org/web/20200110114101/http://www.fa-technik.adfc.de/code/opengeodb/
gefunden werden können.

Dieses Skript ist für die Verwendung mit Python3 gedacht.
Es sollte mit Python 2.x funktionieren, jedoch könnte Unicode mit CSV
ein Problem darstellen.

Getestet mit DE.tsv. Kleinere Änderungen könnten für andere TSVs notwendig sein,
da für verschiedene Länder unterschiedliche Daten gespeichert werden.

Version 1.0
(c) Uli Köhler (2015)
Veröffentlicht unter CC0 1.0 Universal (public domain)
"""
import csv
from collections import namedtuple

__author__  = "Uli Köhler"
__version__ = "1.0"
__license__ = "CC0 1.0 Universal"

PLZEntry = namedtuple('PLZEntry',
    ['loc_id', #OpenGeoDB Location ID
    'ags', # AGS - Amtlicher Gemeindeschluessel
    'ascii', # Normalisierter ASCII-only Großbuchstaben-Ortsname
    'name', # Tatsächlicher (Unicode) Ortsname
    'lat', # Breitengrad in Grad
    'lon', # Längengrad in Grad
    'amt', # Zugehörig zu
    'plz', # Liste von PLZ-Codes
    'vorwahl', # Telefonvorwahl
    'einwohner', # Einwohnerzahl
    'flaeche', # Fläche
    'kz', # KFZ Kennzeichen
    'typ', # ?
    'level', # ?
    'of', # ?
    'invalid'])

def zeroOneToBool(x):
    "Wandelt '0' in False um, alles andere in "
    return False if x == '0' else True

def toFloatDefault(s, default=float('NaN')):
    "Wandelt einen String in einen float um, mit einem Standardwert im Fehlerfall"
    try: return float(s)
    except ValueError: return default

def toIntDefault(s, default=0):
    "Wandelt einen String in einen int um, mit einem Standardwert im Fehlerfall"
    try: return int(s)
    except ValueError: return default

def readTSVFile(filename):
    "Liest eine OpenGeoDB PLZ-TSV-Datei und yielded PLZEntry-Objekte"
    with open(filename) as infile:
        csvreader = csv.reader(infile, delimiter='\t', quotechar='"')
        for row in csvreader:
            if row[0] == "#loc_id": continue # Header überspringen
            yield PLZEntry(toIntDefault(row[0]), row[1], row[2], row[3], toFloatDefault(row[4]), toFloatDefault(row[5]),
                           row[6], row[7].split(","), row[8], toIntDefault(row[9]), toFloatDefault(row[10]), row[11],
                           row[12], row[13], row[14], zeroOneToBool(row[15]))


if __name__ == "__main__":
    #Beispiel für die Verwendung der Funktionen
    import argparse
    parser = argparse.ArgumentParser(description="Den Namen eines Ortes anhand seines PLZ-Codes abrufen")
    parser.add_argument("infile", help="Die OpenGeoDB-TSV-Datei zum Lesen")
    parser.add_argument("plz", help="Nur Eintragsnamen mit dieser PLZ ausgeben")
    args = parser.parse_args()
    #Reader ausführen
    for entry in readTSVFile(args.infile):
        if args.plz in entry.plz:
            print (entry.name)

Check out similar posts by category: Python, Geoinformatics