[PYTHON] Lassen Sie uns die Eisenbahndaten der nationalen Landnummern verwenden

Zweck

Mit dem nationalen Download-Service für numerische Landinformationen können Sie Daten erhalten, die vom Ministerium für Land, Infrastruktur, Verkehr und Tourismus verwaltet werden. Dieses Mal werde ich die Koordinaten auf Google Map anhand von Eisenbahndaten zeichnen.

Demo: http://needtec.sakura.ne.jp/railway_location/railway

GIT: https://github.com/mima3/railway_location

Über Daten

Eisenbahndaten können von der folgenden Seite heruntergeladen werden.

** Nationale Landnummerninformationen Eisenbahndaten ** http://nlftp.mlit.go.jp/ksj/gml/datalist/KsjTmplt-N02-v2_2.html

Informationen zur Verwendung von XML in der heruntergeladenen Datei finden Sie im Folgenden. http://nlftp.mlit.go.jp/ksj/gml/product_spec/KS-PS-N02-v2_1.pdf

Einfach ausgedrückt, enthalten Eisenbahndaten Informationen, die die Form der Linien- und Bahnhofsinformationen anzeigen. Hier sind die wichtigen Elemente: ・ Gml: Kurvenkurveninformationen ・ Ksj: Eisenbahnabschnitt Informationen zum Eisenbahnabschnitt ・ Ksj: Station Stationsinformationen

Koordinateninformationen werden in Curve gespeichert. Die Verknüpfung zu Curve wird im Standortelement von railroadSection and Station gespeichert.

Speicherung in der Datenbank

Da es schwierig ist, eine große Datenmenge in XML zu verarbeiten, wird sie vorübergehend in einer relationalen Datenbank gespeichert.

Zu diesem Zeitpunkt wird eine große XML-Datei analysiert. Wenn jedoch die gesamte XML-Datei einmal im Speicher gespeichert und analysiert wurde, steigt die Speichernutzung dramatisch an und es ist nicht möglich, sie zu verarbeiten. Verwenden Sie daher lxml.etree.iterparse, um nacheinander zu verarbeiten.

Beim Parsen von N02-XX.xml mit lxml.etree.itreparse tritt jedoch ein Fehler auf. Dies liegt daran, dass das XML folgende Zeilen enthält:

 xmlns:schemaLocation="http://nlftp.mlit.go.jp/ksj/schemas/ksj-app KsjAppSchema-N02-v2_0.xsd">

lxml betrachtet den hier angegebenen URI als ungültigen URI und gibt einen Fehler aus. Um dies zu vermeiden, muss beim Parsen von XML in lxml restore = True angegeben werden. http://stackoverflow.com/questions/18692965/how-do-i-skip-validating-the-uri-in-lxml

** Problemumgehung: **

        context = etree.iterparse(
            xml,
            events=('end',),
            tag='{http://www.opengis.net/gml/3.2}Curve',
            recover=True
        )

In iterparse wurde dieses Argument nach lxml == 3.4.1 eingeführt, daher müssen Sie die Version angeben, in der lxml installiert werden soll.

easy_install lxml==3.4.1

Basierend auf dem oben Gesagten erfolgt der Import des XML von Eisenbahndaten in die Datenbank wie folgt.

railway_db.py


# -*- coding: utf-8 -*-
import sqlite3
import sys
import os
# easy_install lxml==3.4.1
from lxml import etree
from peewee import *

database_proxy = Proxy()
database = None


class BaseModel(Model):
    """
Modellklassenbasis
    """
    class Meta:
        database = database_proxy


class Curve(BaseModel):
    """
Kurveninformationsmodell
    """
    curve_id = CharField(index=True, unique=False)
    lat = DoubleField()
    lng = DoubleField()


class RailRoadSection(BaseModel):
    """
Modell für Informationen zum Eisenbahnabschnitt
    """
    gml_id = CharField(primary_key=True)
    #Da der externe Schlüssel einen Primärschlüssel oder eine eindeutige Einschränkung haben muss,
    #Es kann nicht als externer Schlüssel für mehrere Daten angegeben werden.
    location = CharField(index=True)
    railway_type = IntegerField()
    service_provider_type = IntegerField()
    railway_line_name = CharField(index=True)
    operation_company = CharField(index=True)


class Station(BaseModel):
    """
Stationsinformationsmodell
    """
    gml_id = CharField(primary_key=True)
    #Da der externe Schlüssel einen Primärschlüssel oder eine eindeutige Einschränkung haben muss,
    #Es kann nicht als externer Schlüssel für mehrere Daten angegeben werden.
    location = CharField(index=True)
    railway_type = IntegerField()
    service_provider_type = IntegerField()
    railway_line_name = CharField(index=True)
    operation_company = CharField(index=True)
    station_name = CharField(index=True)
    railroad_section = ForeignKeyField(
        db_column='railroad_section_id',
        rel_model=RailRoadSection,
        to_field='gml_id',
        index=True
    )


def setup(path):
    """
Datenbankeinrichtung
    @Parameterpfad Datenbankpfad
    """
    global database
    database = SqliteDatabase(path)
    database_proxy.initialize(database)
    database.create_tables([Curve, RailRoadSection, Station], True)


def import_railway(xml):
    """
Nationales Landnumerisches Institut N02-XX.Importieren Sie Routen- und Stationsinformationen aus XML
    TODO:
Ineffizienter Import externer Schlüssel
    @param xml XML-Pfad
    """
    commit_cnt = 2000  #Fügen Sie jede hier angegebene Nummer ein
    f = None
    contents = None
    namespaces = {
        'ksj': 'http://nlftp.mlit.go.jp/ksj/schemas/ksj-app',
        'gml': 'http://www.opengis.net/gml/3.2',
        'xlink': 'http://www.w3.org/1999/xlink',
        'xsi': 'http://www.w3.org/2001/XMLSchema-instance'
    }

    with database.transaction():
        insert_buff = []
        context = etree.iterparse(
            xml,
            events=('end',),
            tag='{http://www.opengis.net/gml/3.2}Curve',
            recover=True
        )
        for event, curve in context:
            curveId = curve.get('{http://www.opengis.net/gml/3.2}id')
            print (curveId)
            posLists = curve.xpath('.//gml:posList', namespaces=namespaces)
            for posList in posLists:
                points = posList.text.split("\n")
                for point in points:
                    pt = point.strip().split(' ')
                    if len(pt) != 2:
                        continue
                    insert_buff.append({
                        'curve_id': curveId,
                        'lat': float(pt[0]),
                        'lng': float(pt[1])
                    })
                    if len(insert_buff) >= commit_cnt:
                        Curve.insert_many(insert_buff).execute()
                        insert_buff = []
        if len(insert_buff):
            Curve.insert_many(insert_buff).execute()
        insert_buff = []
        context = etree.iterparse(
            xml,
            events=('end',),
            tag='{http://nlftp.mlit.go.jp/ksj/schemas/ksj-app}RailroadSection',
            recover=True
        )
        for event, railroad in context:
            railroadSectionId = railroad.get(
                '{http://www.opengis.net/gml/3.2}id'
            )
            locationId = railroad.find(
                'ksj:location',
                namespaces=namespaces
            ).get('{http://www.w3.org/1999/xlink}href')[1:]
            railwayType = railroad.find(
                'ksj:railwayType', namespaces=namespaces
            ).text
            serviceProviderType = railroad.find(
                'ksj:serviceProviderType',
                namespaces=namespaces
            ).text
            railwayLineName = railroad.find(
                'ksj:railwayLineName',
                namespaces=namespaces
            ).text
            operationCompany = railroad.find(
                'ksj:operationCompany',
                namespaces=namespaces
            ).text
            insert_buff.append({
                'gml_id': railroadSectionId,
                'location': locationId,
                'railway_type': railwayType,
                'service_provider_type': serviceProviderType,
                'railway_line_name': railwayLineName,
                'operation_company': operationCompany
            })
            print (railroadSectionId)
            if len(insert_buff) >= commit_cnt:
                RailRoadSection.insert_many(insert_buff).execute()
                insert_buff = []
        if len(insert_buff):
            RailRoadSection.insert_many(insert_buff).execute()

        insert_buff = []
        context = etree.iterparse(
            xml,
            events=('end',),
            tag='{http://nlftp.mlit.go.jp/ksj/schemas/ksj-app}Station',
            recover=True
        )
        for event, railroad in context:
            stationId = railroad.get('{http://www.opengis.net/gml/3.2}id')
            locationId = railroad.find(
                'ksj:location', namespaces=namespaces
            ).get('{http://www.w3.org/1999/xlink}href')[1:]
            railwayType = railroad.find(
                'ksj:railwayType',
                namespaces=namespaces
            ).text
            serviceProviderType = railroad.find(
                'ksj:serviceProviderType',
                namespaces=namespaces
            ).text
            railwayLineName = railroad.find(
                'ksj:railwayLineName',
                namespaces=namespaces
            ).text
            operationCompany = railroad.find(
                'ksj:operationCompany',
                namespaces=namespaces
            ).text
            stationName = railroad.find(
                'ksj:stationName',
                namespaces=namespaces
            ).text
            railroadSection = railroad.find(
                'ksj:railroadSection',
                namespaces=namespaces
            ).get('{http://www.w3.org/1999/xlink}href')[1:]
            print (stationId)
            insert_buff.append({
                'gml_id': stationId,
                'location': locationId,
                'railway_type': railwayType,
                'service_provider_type': serviceProviderType,
                'railway_line_name': railwayLineName,
                'operation_company': operationCompany,
                'station_name': stationName,
                'railroad_section': RailRoadSection.get(
                    RailRoadSection.gml_id == railroadSection
                )
            })
            if len(insert_buff) >= commit_cnt:
                Station.insert_many(insert_buff).execute()
                insert_buff = []
        if len(insert_buff):
            Station.insert_many(insert_buff).execute()

Einmal in der Datenbank gespeichert, ist der Rest einfach zu bedienen.

Vorsichtsmaßnahmen für den Gebrauch

Die Punkte, die mir beim Umgang mit nationalen numerischen Landinformationen (Eisenbahndaten) aufgefallen sind, sind nachstehend beschrieben.

・ Es ist nicht möglich, nur den Routennamen einzugrenzen. Zum Beispiel kann im Fall von "Linie 1" "Yokohama City" es halten oder "Chiba Monorail" kann es halten. Daher ist es notwendig, nach "Betreiber" und "Routenname" einzugrenzen.

・ Der Name kann sich von dem Namen unterscheiden, den Sie immer verwenden. JR East wurde zur East Japan Passenger Railway und Tokyo Metro zur Tokyo Subway.

・ Die Route kann sich von der Route unterscheiden, die Sie immer verwenden. In einer normalen Routenkarte ist beispielsweise "Tokio" in "Chuo Line" enthalten. "Tokio" ist jedoch nicht als nationale Landnummerninformation in der "Chuo-Linie" enthalten. "Tokyo" - "Kanda" gilt als "Tohoku Line". Dies scheint darauf zurückzuführen zu sein, dass der Abschnitt zwischen der Tokyo Station und der Kanda Station auf einer speziellen Linie verläuft, die auf der Tohoku Main Line verlegt ist.

Recommended Posts

Lassen Sie uns die Eisenbahndaten der nationalen Landnummern verwenden
Versuchen Sie, die Eisenbahndaten der nationalen Landnummern in 3D anzuzeigen
Versuchen Sie, in die Datenbank zu importieren, indem Sie ShapeFile mit numerischen Informationen zum nationalen Land mit Python bearbeiten
Verwenden wir die offenen Daten von "Mamebus" in Python
Lassen Sie uns die Analyse der sinkenden Daten der Titanic so durchführen
Sammeln wir automatisch Unternehmensinformationen (XBRL-Daten) mithilfe der EDINET-API (4/10).
Basiskarteninformationen mithilfe der Python-Geotiff-Konvertierung numerischer Höhendaten
Lassen Sie uns den Gewinner des Bingo bestimmen
Erläutern Sie den Mechanismus der PEP557-Datenklasse
Grundlagen der Quanteninformationstheorie: Datenkomprimierung (1)
Holen Sie sich die Spaltenliste und Datenliste von CASTable
Untersuchen wir den Mechanismus von Kaijis Chinchirorin
Visualisieren Sie die Exportdaten des Piyo-Protokolls
Grundlagen der Quanteninformationstheorie: Datenkomprimierung (2)
Lassen Sie uns den Bevölkerungsübergang von Matsue City, Präfektur Shimane, mit offenen Daten überprüfen