diff --git a/new/stuttgart.geojson b/new/stuttgart.geojson new file mode 100644 index 0000000..a62783e --- /dev/null +++ b/new/stuttgart.geojson @@ -0,0 +1,985 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": { + "id": "stuttgart12717223", + "name": "Haus der Geschichte", + "type": "unknown", + "public_url": null, + "source_url": "https://data.mfdz.de/DATEXII_Parkdaten_dynamisch_Stuttgart/body.xml", + "address": null, + "capacity": 51, + "has_live_capacity": true + }, + "geometry": { + "type": "Point", + "coordinates": [ + 9.185283, + 48.778584 + ] + } + }, + { + "type": "Feature", + "properties": { + "id": "stuttgart12717226", + "name": "Bohnenviertel", + "type": "unknown", + "public_url": null, + "source_url": "https://data.mfdz.de/DATEXII_Parkdaten_dynamisch_Stuttgart/body.xml", + "address": null, + "capacity": 160, + "has_live_capacity": true + }, + "geometry": { + "type": "Point", + "coordinates": [ + 9.183145, + 48.774647 + ] + } + }, + { + "type": "Feature", + "properties": { + "id": "stuttgart12717229", + "name": "Breuninger", + "type": "unknown", + "public_url": null, + "source_url": "https://data.mfdz.de/DATEXII_Parkdaten_dynamisch_Stuttgart/body.xml", + "address": null, + "capacity": 580, + "has_live_capacity": true + }, + "geometry": { + "type": "Point", + "coordinates": [ + 9.181387, + 48.774011 + ] + } + }, + { + "type": "Feature", + "properties": { + "id": "stuttgart12717244", + "name": "Galeria Kaufhof (Rathausviertel)", + "type": "unknown", + "public_url": null, + "source_url": "https://data.mfdz.de/DATEXII_Parkdaten_dynamisch_Stuttgart/body.xml", + "address": null, + "capacity": 111, + "has_live_capacity": true + }, + "geometry": { + "type": "Point", + "coordinates": [ + 9.176942, + 48.774085 + ] + } + }, + { + "type": "Feature", + "properties": { + "id": "stuttgart12717250", + "name": "Parkhaus Hofdiener", + "type": "unknown", + "public_url": null, + "source_url": "https://data.mfdz.de/DATEXII_Parkdaten_dynamisch_Stuttgart/body.xml", + "address": null, + "capacity": 396, + "has_live_capacity": true + }, + "geometry": { + "type": "Point", + "coordinates": [ + 9.172819, + 48.779916 + ] + } + }, + { + "type": "Feature", + "properties": { + "id": "stuttgart12717253", + "name": "Galeria Kaufhof (Unt. Königstr.)", + "type": "unknown", + "public_url": null, + "source_url": "https://data.mfdz.de/DATEXII_Parkdaten_dynamisch_Stuttgart/body.xml", + "address": null, + "capacity": 427, + "has_live_capacity": true + }, + "geometry": { + "type": "Point", + "coordinates": [ + 9.180177, + 48.782109 + ] + } + }, + { + "type": "Feature", + "properties": { + "id": "stuttgart12717256", + "name": "Schloßstraße", + "type": "unknown", + "public_url": null, + "source_url": "https://data.mfdz.de/DATEXII_Parkdaten_dynamisch_Stuttgart/body.xml", + "address": null, + "capacity": 290, + "has_live_capacity": true + }, + "geometry": { + "type": "Point", + "coordinates": [ + 9.16931, + 48.778428 + ] + } + }, + { + "type": "Feature", + "properties": { + "id": "stuttgart12717262", + "name": "City-Garage", + "type": "unknown", + "public_url": null, + "source_url": "https://data.mfdz.de/DATEXII_Parkdaten_dynamisch_Stuttgart/body.xml", + "address": null, + "capacity": 140, + "has_live_capacity": true + }, + "geometry": { + "type": "Point", + "coordinates": [ + 9.176438, + 48.78265 + ] + } + }, + { + "type": "Feature", + "properties": { + "id": "stuttgart12717289", + "name": "Österreichischer Platz", + "type": "unknown", + "public_url": null, + "source_url": "https://data.mfdz.de/DATEXII_Parkdaten_dynamisch_Stuttgart/body.xml", + "address": null, + "capacity": 564, + "has_live_capacity": true + }, + "geometry": { + "type": "Point", + "coordinates": [ + 9.17371, + 48.770046 + ] + } + }, + { + "type": "Feature", + "properties": { + "id": "stuttgart12717312", + "name": "Im Zeppelin Carré", + "type": "unknown", + "public_url": null, + "source_url": "https://data.mfdz.de/DATEXII_Parkdaten_dynamisch_Stuttgart/body.xml", + "address": null, + "capacity": 265, + "has_live_capacity": true + }, + "geometry": { + "type": "Point", + "coordinates": [ + 9.17841, + 48.782886 + ] + } + }, + { + "type": "Feature", + "properties": { + "id": "stuttgart12717315", + "name": "Züblin", + "type": "unknown", + "public_url": null, + "source_url": "https://data.mfdz.de/DATEXII_Parkdaten_dynamisch_Stuttgart/body.xml", + "address": null, + "capacity": 520, + "has_live_capacity": true + }, + "geometry": { + "type": "Point", + "coordinates": [ + 9.18126, + 48.772869 + ] + } + }, + { + "type": "Feature", + "properties": { + "id": "stuttgart12717345", + "name": "Friedrichsbau", + "type": "unknown", + "public_url": null, + "source_url": "https://data.mfdz.de/DATEXII_Parkdaten_dynamisch_Stuttgart/body.xml", + "address": null, + "capacity": 141, + "has_live_capacity": true + }, + "geometry": { + "type": "Point", + "coordinates": [ + 9.175678, + 48.780101 + ] + } + }, + { + "type": "Feature", + "properties": { + "id": "stuttgart12717363", + "name": "Liederhalle / Bosch-Areal", + "type": "unknown", + "public_url": null, + "source_url": "https://data.mfdz.de/DATEXII_Parkdaten_dynamisch_Stuttgart/body.xml", + "address": null, + "capacity": 110, + "has_live_capacity": true + }, + "geometry": { + "type": "Point", + "coordinates": [ + 9.167902, + 48.77915 + ] + } + }, + { + "type": "Feature", + "properties": { + "id": "stuttgart12717366", + "name": "Holzgartenstraße", + "type": "unknown", + "public_url": null, + "source_url": "https://data.mfdz.de/DATEXII_Parkdaten_dynamisch_Stuttgart/body.xml", + "address": null, + "capacity": 194, + "has_live_capacity": true + }, + "geometry": { + "type": "Point", + "coordinates": [ + 9.169934, + 48.780186 + ] + } + }, + { + "type": "Feature", + "properties": { + "id": "stuttgart12717372", + "name": "Königsbau Passagen", + "type": "unknown", + "public_url": null, + "source_url": "https://data.mfdz.de/DATEXII_Parkdaten_dynamisch_Stuttgart/body.xml", + "address": null, + "capacity": 312, + "has_live_capacity": true + }, + "geometry": { + "type": "Point", + "coordinates": [ + 9.177845, + 48.779949 + ] + } + }, + { + "type": "Feature", + "properties": { + "id": "stuttgart12717375", + "name": "Kronprinzstraße", + "type": "unknown", + "public_url": null, + "source_url": "https://data.mfdz.de/DATEXII_Parkdaten_dynamisch_Stuttgart/body.xml", + "address": null, + "capacity": 564, + "has_live_capacity": true + }, + "geometry": { + "type": "Point", + "coordinates": [ + 9.174055, + 48.775336 + ] + } + }, + { + "type": "Feature", + "properties": { + "id": "stuttgart12717384", + "name": "Landtag", + "type": "unknown", + "public_url": null, + "source_url": "https://data.mfdz.de/DATEXII_Parkdaten_dynamisch_Stuttgart/body.xml", + "address": null, + "capacity": 140, + "has_live_capacity": true + }, + "geometry": { + "type": "Point", + "coordinates": [ + 9.18462, + 48.778693 + ] + } + }, + { + "type": "Feature", + "properties": { + "id": "stuttgart12717408", + "name": "Rotebühlplatz/Kulturzentrum", + "type": "unknown", + "public_url": null, + "source_url": "https://data.mfdz.de/DATEXII_Parkdaten_dynamisch_Stuttgart/body.xml", + "address": null, + "capacity": 270, + "has_live_capacity": true + }, + "geometry": { + "type": "Point", + "coordinates": [ + 9.169756, + 48.775774 + ] + } + }, + { + "type": "Feature", + "properties": { + "id": "stuttgart12717411", + "name": "Schillerplatz", + "type": "unknown", + "public_url": null, + "source_url": "https://data.mfdz.de/DATEXII_Parkdaten_dynamisch_Stuttgart/body.xml", + "address": null, + "capacity": 158, + "has_live_capacity": true + }, + "geometry": { + "type": "Point", + "coordinates": [ + 9.178785, + 48.776763 + ] + } + }, + { + "type": "Feature", + "properties": { + "id": "stuttgart12717414", + "name": "Schloßgarten (verbunden mit Marstallstraße)", + "type": "unknown", + "public_url": null, + "source_url": "https://data.mfdz.de/DATEXII_Parkdaten_dynamisch_Stuttgart/body.xml", + "address": null, + "capacity": 385, + "has_live_capacity": true + }, + "geometry": { + "type": "Point", + "coordinates": [ + 9.182805, + 48.782177 + ] + } + }, + { + "type": "Feature", + "properties": { + "id": "stuttgart12717417", + "name": "Schwabenzentrum", + "type": "unknown", + "public_url": null, + "source_url": "https://data.mfdz.de/DATEXII_Parkdaten_dynamisch_Stuttgart/body.xml", + "address": null, + "capacity": 385, + "has_live_capacity": true + }, + "geometry": { + "type": "Point", + "coordinates": [ + 9.178976, + 48.77352 + ] + } + }, + { + "type": "Feature", + "properties": { + "id": "stuttgart12717426", + "name": "Sophiengarage", + "type": "unknown", + "public_url": null, + "source_url": "https://data.mfdz.de/DATEXII_Parkdaten_dynamisch_Stuttgart/body.xml", + "address": null, + "capacity": 181, + "has_live_capacity": true + }, + "geometry": { + "type": "Point", + "coordinates": [ + 9.172171, + 48.773665 + ] + } + }, + { + "type": "Feature", + "properties": { + "id": "stuttgart12717429", + "name": "Staatsgalerie", + "type": "unknown", + "public_url": null, + "source_url": "https://data.mfdz.de/DATEXII_Parkdaten_dynamisch_Stuttgart/body.xml", + "address": null, + "capacity": 291, + "has_live_capacity": true + }, + "geometry": { + "type": "Point", + "coordinates": [ + 9.186664, + 48.780417 + ] + } + }, + { + "type": "Feature", + "properties": { + "id": "stuttgart12717432", + "name": "Stadtgarten (Katharinenhospital)", + "type": "unknown", + "public_url": null, + "source_url": "https://data.mfdz.de/DATEXII_Parkdaten_dynamisch_Stuttgart/body.xml", + "address": null, + "capacity": 135, + "has_live_capacity": true + }, + "geometry": { + "type": "Point", + "coordinates": [ + 9.173002, + 48.782484 + ] + } + }, + { + "type": "Feature", + "properties": { + "id": "stuttgart12717435", + "name": "Stephangarage", + "type": "unknown", + "public_url": null, + "source_url": "https://data.mfdz.de/DATEXII_Parkdaten_dynamisch_Stuttgart/body.xml", + "address": null, + "capacity": 265, + "has_live_capacity": true + }, + "geometry": { + "type": "Point", + "coordinates": [ + 9.17985, + 48.781993 + ] + } + }, + { + "type": "Feature", + "properties": { + "id": "stuttgart12717441", + "name": "LBBW (Hbf.)", + "type": "unknown", + "public_url": null, + "source_url": "https://data.mfdz.de/DATEXII_Parkdaten_dynamisch_Stuttgart/body.xml", + "address": null, + "capacity": 870, + "has_live_capacity": true + }, + "geometry": { + "type": "Point", + "coordinates": [ + 9.181171, + 48.786421 + ] + } + }, + { + "type": "Feature", + "properties": { + "id": "stuttgart12717447", + "name": "Tivoli", + "type": "unknown", + "public_url": null, + "source_url": "https://data.mfdz.de/DATEXII_Parkdaten_dynamisch_Stuttgart/body.xml", + "address": null, + "capacity": 213, + "has_live_capacity": true + }, + "geometry": { + "type": "Point", + "coordinates": [ + 9.166417, + 48.779737 + ] + } + }, + { + "type": "Feature", + "properties": { + "id": "stuttgart12717450", + "name": "Tübinger Carre", + "type": "unknown", + "public_url": null, + "source_url": "https://data.mfdz.de/DATEXII_Parkdaten_dynamisch_Stuttgart/body.xml", + "address": null, + "capacity": 0, + "has_live_capacity": true + }, + "geometry": { + "type": "Point", + "coordinates": [ + 9.175405, + 48.772131 + ] + } + }, + { + "type": "Feature", + "properties": { + "id": "stuttgart12718752", + "name": "Das Gerber", + "type": "unknown", + "public_url": null, + "source_url": "https://data.mfdz.de/DATEXII_Parkdaten_dynamisch_Stuttgart/body.xml", + "address": null, + "capacity": 573, + "has_live_capacity": true + }, + "geometry": { + "type": "Point", + "coordinates": [ + 9.172763, + 48.771298 + ] + } + }, + { + "type": "Feature", + "properties": { + "id": "stuttgart12718764", + "name": "Milaneo", + "type": "unknown", + "public_url": null, + "source_url": "https://data.mfdz.de/DATEXII_Parkdaten_dynamisch_Stuttgart/body.xml", + "address": null, + "capacity": 1104, + "has_live_capacity": true + }, + "geometry": { + "type": "Point", + "coordinates": [ + 9.183978, + 48.791373 + ] + } + }, + { + "type": "Feature", + "properties": { + "id": "stuttgart12718779", + "name": "Rotebühlhof/Finanzamt", + "type": "unknown", + "public_url": null, + "source_url": "https://data.mfdz.de/DATEXII_Parkdaten_dynamisch_Stuttgart/body.xml", + "address": null, + "capacity": 213, + "has_live_capacity": true + }, + "geometry": { + "type": "Point", + "coordinates": [ + 9.169377, + 48.773881 + ] + } + }, + { + "type": "Feature", + "properties": { + "id": "stuttgart78241073", + "name": "Rathaus", + "type": "unknown", + "public_url": null, + "source_url": "https://data.mfdz.de/DATEXII_Parkdaten_dynamisch_Stuttgart/body.xml", + "address": null, + "capacity": 0, + "has_live_capacity": true + }, + "geometry": { + "type": "Point", + "coordinates": [ + 9.177875, + 48.774178 + ] + } + }, + { + "type": "Feature", + "properties": { + "id": "stuttgart78241093", + "name": "Neue Brücke", + "type": "unknown", + "public_url": null, + "source_url": "https://data.mfdz.de/DATEXII_Parkdaten_dynamisch_Stuttgart/body.xml", + "address": null, + "capacity": 150, + "has_live_capacity": true + }, + "geometry": { + "type": "Point", + "coordinates": [ + 4.511338, + 0.00044 + ] + } + }, + { + "type": "Feature", + "properties": { + "id": "stuttgart78257172", + "name": "Keplerstraße", + "type": "unknown", + "public_url": null, + "source_url": "https://data.mfdz.de/DATEXII_Parkdaten_dynamisch_Stuttgart/body.xml", + "address": null, + "capacity": 163, + "has_live_capacity": true + }, + "geometry": { + "type": "Point", + "coordinates": [ + 9.175941, + 48.781351 + ] + } + }, + { + "type": "Feature", + "properties": { + "id": "stuttgart78278431", + "name": "Landesbibliothek", + "type": "unknown", + "public_url": null, + "source_url": "https://data.mfdz.de/DATEXII_Parkdaten_dynamisch_Stuttgart/body.xml", + "address": null, + "capacity": 216, + "has_live_capacity": true + }, + "geometry": { + "type": "Point", + "coordinates": [ + 9.185307, + 48.777837 + ] + } + }, + { + "type": "Feature", + "properties": { + "id": "stuttgart78278545", + "name": "Kriegsberg", + "type": "unknown", + "public_url": null, + "source_url": "https://data.mfdz.de/DATEXII_Parkdaten_dynamisch_Stuttgart/body.xml", + "address": null, + "capacity": 247, + "has_live_capacity": true + }, + "geometry": { + "type": "Point", + "coordinates": [ + 9.17651, + 48.78449 + ] + } + }, + { + "type": "Feature", + "properties": { + "id": "stuttgart78278577", + "name": "P+R Österfeld", + "type": "unknown", + "public_url": null, + "source_url": "https://data.mfdz.de/DATEXII_Parkdaten_dynamisch_Stuttgart/body.xml", + "address": null, + "capacity": 284, + "has_live_capacity": true + }, + "geometry": { + "type": "Point", + "coordinates": [ + 9.112993, + 48.737102 + ] + } + }, + { + "type": "Feature", + "properties": { + "id": "stuttgart78278879", + "name": "Bülow Carre", + "type": "unknown", + "public_url": null, + "source_url": "https://data.mfdz.de/DATEXII_Parkdaten_dynamisch_Stuttgart/body.xml", + "address": null, + "capacity": 108, + "has_live_capacity": true + }, + "geometry": { + "type": "Point", + "coordinates": [ + 9.178908, + 48.781202 + ] + } + }, + { + "type": "Feature", + "properties": { + "id": "stuttgart78279135", + "name": "Dorotheen-Quartier", + "type": "unknown", + "public_url": null, + "source_url": "https://data.mfdz.de/DATEXII_Parkdaten_dynamisch_Stuttgart/body.xml", + "address": null, + "capacity": 270, + "has_live_capacity": true + }, + "geometry": { + "type": "Point", + "coordinates": [ + 9.181663, + 48.77527 + ] + } + }, + { + "type": "Feature", + "properties": { + "id": "stuttgart78280073", + "name": "P+R Albstraße", + "type": "unknown", + "public_url": null, + "source_url": "https://data.mfdz.de/DATEXII_Parkdaten_dynamisch_Stuttgart/body.xml", + "address": null, + "capacity": 100, + "has_live_capacity": true + }, + "geometry": { + "type": "Point", + "coordinates": [ + 9.161997, + 48.745698 + ] + } + }, + { + "type": "Feature", + "properties": { + "id": "stuttgart78318611", + "name": "Haus der Wirtschaft", + "type": "unknown", + "public_url": null, + "source_url": "https://data.mfdz.de/DATEXII_Parkdaten_dynamisch_Stuttgart/body.xml", + "address": null, + "capacity": 74, + "has_live_capacity": true + }, + "geometry": { + "type": "Point", + "coordinates": [ + 9.174066, + 48.778421 + ] + } + }, + { + "type": "Feature", + "properties": { + "id": "stuttgart78319371", + "name": "Marquardtbau", + "type": "unknown", + "public_url": null, + "source_url": "https://data.mfdz.de/DATEXII_Parkdaten_dynamisch_Stuttgart/body.xml", + "address": null, + "capacity": 0, + "has_live_capacity": true + }, + "geometry": { + "type": "Point", + "coordinates": [ + 9.178482, + 48.780142 + ] + } + }, + { + "type": "Feature", + "properties": { + "id": "stuttgart78319401", + "name": "Stadtmitte", + "type": "unknown", + "public_url": null, + "source_url": "https://data.mfdz.de/DATEXII_Parkdaten_dynamisch_Stuttgart/body.xml", + "address": null, + "capacity": 0, + "has_live_capacity": true + }, + "geometry": { + "type": "Point", + "coordinates": [ + 9.175917, + 48.778301 + ] + } + }, + { + "type": "Feature", + "properties": { + "id": "stuttgart78319431", + "name": "Am Bollwerk", + "type": "unknown", + "public_url": null, + "source_url": "https://data.mfdz.de/DATEXII_Parkdaten_dynamisch_Stuttgart/body.xml", + "address": null, + "capacity": 0, + "has_live_capacity": true + }, + "geometry": { + "type": "Point", + "coordinates": [ + 9.167501, + 48.777108 + ] + } + }, + { + "type": "Feature", + "properties": { + "id": "stuttgart78319463", + "name": "Am Schloßplatz", + "type": "unknown", + "public_url": null, + "source_url": "https://data.mfdz.de/DATEXII_Parkdaten_dynamisch_Stuttgart/body.xml", + "address": null, + "capacity": 0, + "has_live_capacity": true + }, + "geometry": { + "type": "Point", + "coordinates": [ + 9.181136, + 48.780039 + ] + } + }, + { + "type": "Feature", + "properties": { + "id": "stuttgart78319492", + "name": "Wilhelma", + "type": "unknown", + "public_url": null, + "source_url": "https://data.mfdz.de/DATEXII_Parkdaten_dynamisch_Stuttgart/body.xml", + "address": null, + "capacity": 0, + "has_live_capacity": true + }, + "geometry": { + "type": "Point", + "coordinates": [ + 9.20658, + 48.803817 + ] + } + }, + { + "type": "Feature", + "properties": { + "id": "stuttgart78357190", + "name": "BW-Bank/Kunstmuseum", + "type": "unknown", + "public_url": null, + "source_url": "https://data.mfdz.de/DATEXII_Parkdaten_dynamisch_Stuttgart/body.xml", + "address": null, + "capacity": 0, + "has_live_capacity": true + }, + "geometry": { + "type": "Point", + "coordinates": [ + 9.176231, + 48.77876 + ] + } + }, + { + "type": "Feature", + "properties": { + "id": "stuttgart78357200", + "name": "Olgahospital", + "type": "unknown", + "public_url": null, + "source_url": "https://data.mfdz.de/DATEXII_Parkdaten_dynamisch_Stuttgart/body.xml", + "address": null, + "capacity": 0, + "has_live_capacity": true + }, + "geometry": { + "type": "Point", + "coordinates": [ + 9.17433, + 48.784052 + ] + } + }, + { + "type": "Feature", + "properties": { + "id": "stuttgart78357206", + "name": "Le Méridian", + "type": "unknown", + "public_url": null, + "source_url": "https://data.mfdz.de/DATEXII_Parkdaten_dynamisch_Stuttgart/body.xml", + "address": null, + "capacity": 0, + "has_live_capacity": true + }, + "geometry": { + "type": "Point", + "coordinates": [ + 9.189266, + 48.784514 + ] + } + } + ] +} \ No newline at end of file diff --git a/new/stuttgart.py b/new/stuttgart.py new file mode 100644 index 0000000..9445542 --- /dev/null +++ b/new/stuttgart.py @@ -0,0 +1,41 @@ +from typing import List + +import pyproj + +from util import * + + +class Stuttgart(DatexScraperMixin, ScraperBase): + """ + This Scraper scrapes the re-published datex publications of the city of Stuttgart, to avoid + the currently still necessary certifcates for MDM data portal access. + + Note: the static publication currently doesn't publish some important information like coordinates, + type, address. I (Holger Bruch) contacted the data owner and asked for additional information in the + publication. + + In case this information will not be provided soon, the geojson will need to be enhanced manually :-/ + """ + + POOL = PoolInfo( + id='stuttgart', + name='Stuttgart', + public_url='https://service.mdm-portal.de/mdm-portal-application/publDetail.do?publicationId=3059002', + source_url='https://data.mfdz.de/DATEXII_Parkdaten_dynamisch_Stuttgart/body.xml', + attribution_contributor='Landeshauptstadt Stuttgart, Tiefbauamt, mirrored by MFDZ', + attribution_license='dl-de/by-2-0', + ) + + STATIC_LOTS_URL = 'https://data.mfdz.de/DATEXII_Parkdaten_statisch_Stuttgart/body.xml' + + UTM32_PROJ = pyproj.Proj(proj='utm', zone=32, ellps='WGS84', preserve_units=True) + + def _get_facility_coords(self, facility): + umt32_coord = super()._get_facility_coords(facility) + + if umt32_coord == None: + return None + + wgs84_coord = self.UTM32_PROJ(umt32_coord['longitude'], umt32_coord['latitude'], inverse=True) + + return {'latitude': round(wgs84_coord[1], 6), 'longitude': round(wgs84_coord[0], 6)} diff --git a/requirements.txt b/requirements.txt index 7787cd1..2f13044 100644 --- a/requirements.txt +++ b/requirements.txt @@ -19,3 +19,5 @@ validataclass~=0.9.0 openpyxl~=3.1.2 lxml~=4.9.3 +# Stuttgart returns UTM32 coords, so we reproject using pyproj +pyproj~=3.6.1 diff --git a/util/__init__.py b/util/__init__.py index b70f211..51d2f95 100644 --- a/util/__init__.py +++ b/util/__init__.py @@ -11,3 +11,4 @@ from .scraper import ScraperBase from .soup import get_soup_text from .structs import PoolInfo, LotInfo, LotData, LotInfoList, LotDataList, PoolInfo as SourceInfo +from .datex import DatexScraperMixin diff --git a/util/datex.py b/util/datex.py new file mode 100644 index 0000000..81ed734 --- /dev/null +++ b/util/datex.py @@ -0,0 +1,117 @@ +from typing import List + +from .strings import guess_lot_type, name_to_legacy_id, parse_geojson +from .structs import LotData, LotInfo + + +class DatexScraperMixin: + """ + This Mixin defines provides an implementation of get_lot_data and + get_lot_infos that should work with most DATEXII ParkingFacility publications. + + Subclasses should provide the dynamic parking facility publication url as POOl.source_url + and the static parking facility publication as class variable: + + STATIC_LOTS_URL: str + + See stuttgart.py for an example. + + """ + + def get_lot_data(self) -> List[LotData]: + now = self.now() + soup = self.request_soup(self.POOL.source_url, encoding='UTF-8', parser='xml') + + last_updated = self.to_utc_datetime(soup.find('publicationTime').text) + + lots = [] + + for facility in soup.select('parkingFacilityTableStatusPublication > parkingFacilityStatus'): + lot_id = facility.find('parkingFacilityReference')['id'] + + capacity_shorttermoverride = facility.find('totalParkingCapacityShorttermOverride') + + parkingFacilityStatusTime = facility.find('parkingFacilityStatusTime') + try: + lot_timestamp = self.to_utc_datetime(parkingFacilityStatusTime.text) if parkingFacilityStatusTime else last_updated + except: + lot_timestamp = last_updated + # TODO: Need not find out difference between + # totalNumberOfOccupiedParkingSpaces and totalNumberOfVacantParkingSpaces + # e.g. first goes to zero or might disappear when closed while second remains + try: + lot_occupied = int(facility.find('totalNumberOfOccupiedParkingSpaces').text) + except: + lot_occupied = None + + try: + lot_free = int(facility.find('totalNumberOfVacantParkingSpaces').text) + except: + lot_free = None + + state = facility.find('parkingFacilityStatus') + + if state and state.text in [LotData.Status.open, LotData.Status.closed]: + state = state.text + elif state and state.text == 'spacesAvailable': + state = LotData.Status.open + else: + state = LotData.Status.nodata + + lots.append( + LotData( + id=name_to_legacy_id(self.POOL.id, lot_id), + timestamp=now, + lot_timestamp=lot_timestamp, + status=state, + num_occupied=lot_occupied, + num_free=lot_free, + capacity=int(capacity_shorttermoverride.text) if capacity_shorttermoverride else None, + ) + ) + + return lots + + def get_lot_infos(self) -> List[LotInfo]: + url = self.STATIC_LOTS_URL + soup = self.request_soup(url, encoding='UTF-8', parser='xml') + + lots = [] + for facility in soup.find_all('parkingFacility'): + coord = self._get_facility_coords(facility) + lots.append( + LotInfo( + id=name_to_legacy_id(self.POOL.id, facility['id']), + name=self._get_facility_name(facility), + type=LotInfo.Types.unknown, # there's no data + source_url=self.POOL.source_url, + latitude=coord['latitude'] if coord else None, + longitude=coord['longitude'] if coord else None, + capacity=int(facility.find('totalParkingCapacity').text), + has_live_capacity=True, + ) + ) + + return lots + + def _get_facility_name(self, facility): + # Try name (used by Stuttgart) + pfname = facility.select_one('parkingFacilityName > values > value') + if pfname: + return pfname.text + + # If not, try parkingfacilitydescription (as (misused?) by Frankfurt) + dfdesc = facility.find('parkingfacilitydescription') + if dfdesc: + return dfdesc.text + + return None + + def _get_facility_coords(self, facility): + point = facility.find('pointCoordinates') + if not point: + point = facility.find('locationForDisplay') + if not point: + return None + + return {'latitude': float(point.find('latitude').text), 'longitude': float(point.find('longitude').text)}