From e341a652040fbc947442ed4c64764b372db7638a Mon Sep 17 00:00:00 2001 From: Marco Schmid Date: Mon, 11 May 2026 18:13:06 +0200 Subject: [PATCH] Task_6: Adapter, load- und fetch-Funktionen --- TASK.md | 44 +++++++++++------------------ src/overpass/__init__.py | 0 src/overpass/main.py | 40 ++++++++++++++++++++++++++ main.py => src/overpass/overpass.py | 35 ++++++++++++++--------- 4 files changed, 78 insertions(+), 41 deletions(-) create mode 100644 src/overpass/__init__.py create mode 100644 src/overpass/main.py rename main.py => src/overpass/overpass.py (73%) diff --git a/TASK.md b/TASK.md index 4224880..d11e47f 100644 --- a/TASK.md +++ b/TASK.md @@ -1,31 +1,21 @@ -# TASK 5: +# TASK 6: -Als Nächstes versuchen wir unsere `main.py` von Businesslogik zu befreien und verlagern diese in ein eigenes Modul. +Wir arbeiten nun intern direkt mit den Daten von Overpass, will heissen `results` hat die gleiche Struktur wie die Daten, +welche von Overpass kommen. Macht das Sinn? Warum vielleicht nicht? -* verlagert dazu die Logik von 'fetch_bergbahnen' in ein eigenes Modul `overpass.py` aus. -* nennt die Funktion allgemeiner `fetch_overpass` (anstelle `fetch_bergbahnen`) -> somit würde es Sinn - machen, wenn wir den Query der Funktion als Argument mitgeben könnten (ist genereller). -* Erstellt in diesem `main.py` eine eigene 'main-Funktion', welche nur die Hauptlogik beinhalten und somit `fetch_overpass` - importiert und aufruft +* Wir versuchen einen Adapter zu bauen. Intern wollen wir mit einer eigenen Dataclass `POI` arbeiten. Wir bauen also dazu eine + Funktion `load_pois`, welche einerseits die Daten fetched und andererseits auch parsed. Den Fetching-Teil haben wir + bereits (`fetch_overpass`), den Pasing-Teil haben wir noch nicht. + Schreibt bitte eine eigene Dataclass`Poi` in welche die gefetchten Daten 'abgefüllt' werden können. +* Die Datenklasse `POI` könnt ihr in einem neuen Modul `models.py` ablegen. +* Die Struktur von `POI` sieht z.B. wie folgt aus: ``` -overpass/ -├── src/ -│ └── overpass/ -│ ├── __init__.py -│ ├── main.py -│ ├── overpass.py -├── tests/ -│ └── test_...py -├── .env -├── .gitignore -├── requirements.txt -└── pyproject.toml -``` - -**Anmerkungen:** - -* `requirements.txt` ist nicht falsch, aber `pyproject.toml` ist seit PEP 517/518 der aktuelle - Standard — auch für einfache Projekte -* `.env` beinhaltet später unsere (geschützten) Environment-Variablen. Diese sollen aus sicherheitsgründen - NIE auf git gepushed werden und werden deshalb auch in `.gitignore` vermerkt. \ No newline at end of file +class POI: + id: str + type: str + poi_type: str + lat: float + lon: float + tags: dict +``` \ No newline at end of file diff --git a/src/overpass/__init__.py b/src/overpass/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/overpass/main.py b/src/overpass/main.py new file mode 100644 index 0000000..916c22b --- /dev/null +++ b/src/overpass/main.py @@ -0,0 +1,40 @@ +from overpass import fetch_overpass, OverpassApiError + +# --------------------------------------------------------------------------- +# Konfiguration +# --------------------------------------------------------------------------- + +BBOXEN = { + "davos": (46.72, 9.70, 46.92, 10.00), + "schweiz": (45.8, 5.9, 47.8, 10.5), +} + +QUERY = """ + [out:json][timeout:2][maxsize:500000]; + ( + node["aerialway"="station"]({bbox}); + way["aerialway"="station"]({bbox}); + node["railway"="funicular"]({bbox}); + way["railway"="funicular"]({bbox}); + node["railway"="station"]["funicular"="yes"]({bbox}); + ); + out center body; + """ + + +# --------------------------------------------------------------------------- +# Hauptlogik +# --------------------------------------------------------------------------- +def main() -> None: + for name, bbox in BBOXEN.items(): + try: + result = fetch_overpass(overpass_query=QUERY, bbox=bbox) + except OverpassApiError as exc: + print(f" Fehler : {exc}") + continue + + elements = result.get("elements", []) + print(elements) + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/main.py b/src/overpass/overpass.py similarity index 73% rename from main.py rename to src/overpass/overpass.py index 433793c..803d0e2 100644 --- a/main.py +++ b/src/overpass/overpass.py @@ -4,29 +4,23 @@ from pprint import pprint OVERPASS_URL = "https://overpass-api.de/api/interpreter" -BERGBAHN_QUERY = """ -[out:json][timeout:3][maxsize:500000]; -( - node["aerialway"="station"]({bbox}); - way["aerialway"="station"]({bbox}); - node["railway"="funicular"]({bbox}); - way["railway"="funicular"]({bbox}); - node["railway"="station"]["funicular"="yes"]({bbox}); -); -out center body; -""" class OverpassApiError(Exception): pass -def fetch_bergbahnen(bbox: tuple) -> dict: +def fetch_overpass(overpass_query: str, bbox: tuple) -> dict: """ Fragt die Overpass API nach Bergbahnen in der angegebenen Bounding Box ab. Sendet einen HTTP-POST-Request an die Overpass API und gibt die geparste JSON-Antwort zurück. Args: + overpass_query (str): Overpass-QL-Query mit dem Platzhalter {bbox}. + Beispiel: + '[out:json][timeout:5]; + (node["aerialway"="station"]({bbox});); + out center body;' bbox (tuple): Bounding Box als 4-Tuple in Dezimalgrad: (south, west, north, east) Beispiel Davos: (46.72, 9.70, 46.92, 10.00) @@ -59,7 +53,7 @@ def fetch_bergbahnen(bbox: tuple) -> dict: """ bbox_str = ",".join(map(str, bbox)) - query = BERGBAHN_QUERY.format(bbox=bbox_str) + query = overpass_query.format(bbox=bbox_str) try: response = requests.post( @@ -78,6 +72,19 @@ def fetch_bergbahnen(bbox: tuple) -> dict: if __name__ == "__main__": + BERGBAHN_QUERY = """ + [out:json][timeout:2][maxsize:500000]; + ( + node["aerialway"="station"]({bbox}); + way["aerialway"="station"]({bbox}); + node["railway"="funicular"]({bbox}); + way["railway"="funicular"]({bbox}); + node["railway"="station"]["funicular"="yes"]({bbox}); + ); + out center body; + """ + bbox = (46.72, 9.70, 46.92, 10.00) - result = fetch_bergbahnen(bbox) + # bbox = (45.8, 5.9, 47.8, 10.5) + result = fetch_overpass(overpass_query=BERGBAHN_QUERY, bbox=bbox) pprint(result) \ No newline at end of file