python Bahnfahrplan abfragen

OP #8042482
Lesenswert?

Ich will den Fahrplan der Bahn mittels Python abfrage und auswerten. Theoretisch wäre das mit der Libray "schiene" ziemlich einfach:

1
import schiene
2
s = schiene.Schiene()
3

4
# Find connections from Mannheim Hbf to Stuttgart Hbf
5
connections = s.connections('Berlin Hbf', 'Hannover Hbf')
6
print(connections)

Praktisch geht es aber nicht. Kennt jemand da eine Möglichkeit?

OP #8042493
Lesenswert?

Frank D. schrieb:

https://v6.db.transport.rest/getting-started.html

Danke, die API funktioniert. Sie scheint aber wesentlich komplizierter als die ursprüngliche "schiene" Library.

Hier das gerade probierte Beispiel für die Verbindung von Stuttgart nach München:

1
import requests
2
import time
3
from datetime import datetime
4

5
def suche_stop(query):
6
    url = f"https://v6.db.transport.rest/locations?query={query}&results=5"
7
    try:
8
        resp = requests.get(url, timeout=10)
9
        if resp.status_code == 200:
10
            data = resp.json()
11
            print("Gefundene Stops:")
12
            for s in data:
13
                print(f"- ID: {s['id']}, Name: {s['name']}")
14
            return data[0]['id'] if data else None
15
        else:
16
            print(f"Suche-Fehler: {resp.status_code} - {resp.text}")
17
    except Exception as e:
18
        print(f"Netzwerkfehler: {e}")
19
    return None
20

21
def verbindungen(from_id, to_id, results=5, when=None):
22
    url = "https://v6.db.transport.rest/journeys"
23
    params = {
24
        'from': from_id,
25
        'to': to_id,
26
        'results': results,
27
        'language': 'de'
28
    }
29
    if when:
30
        params['when'] = when  # z.B. '2026-04-27T18:00'
31
    try:
32
        resp = requests.get(url, params=params, timeout=15)
33
        print(f"Status: {resp.status_code}")
34
        if resp.status_code == 200:
35
            data = resp.json()
36
            journeys = data.get('journeys', [])
37
            print(f"\n{len(journeys)} beste Verbindungen Stuttgart → München (Stand: {datetime.now().strftime('%H:%M')}):")
38
            for i, j in enumerate(journeys[:3], 1):  # Erste 3
39
                duration = j.get('duration', 'N/A')
40
                legs_count = len(j.get('legs', []))
41
                first_leg = j['legs'][0]
42
                dep_time = first_leg['departure']
43
                print(f"\n{i}. Dauer: {duration}, {legs_count} Etappe(n)")
44
                print(f"   Abfahrt: {dep_time} {first_leg.get('line', {}).get('name', 'Fußweg')}")
45
                print(f"   Ziel: {j['legs'][-1]['arrival']} {j['legs'][-1].get('line', {}).get('name', '')}")
46
        elif resp.status_code == 500:
47
            print("Serverfehler (500): Retry in 60s...")
48
            time.sleep(60)
49
            return verbindungen(from_id, to_id, results)
50
        else:
51
            print(f"Fehler: {resp.status_code} - {resp.text[:300]}")
52
    except Exception as e:
53
        print(f"Ausnahme: {e}")
54

55
if __name__ == "__main__":
56
    from_stop = suche_stop("Stuttgart Hbf")
57
    to_stop = suche_stop("München Hbf")
58
    if from_stop and to_stop:
59
        verbindungen(from_stop, to_stop)
(Firma: LAPD) #8042580
Lesenswert?

Christoph M. schrieb:

Die Anzahl der Anfragen scheint auch begrenzt zu sein. Ich habe das jetzt vielleicht 10x hintereinander gemacht und dann kommt:

Doku: API status .. Also, the new underlying APIs seem to have a much lower rate limit than the old HAFAS API. ⚠️

....

No API Key You can just use the API without authentication. There's a rate limit of 100 requests/minute set up.

#8042602
Lesenswert?

Christoph M. schrieb:

Frank D. schrieb:

https://v6.db.transport.rest/getting-started.html

Danke, die API funktioniert.

Die "schiene"-Library [1] ist offenbar seit einiger Zeit nicht mehr gepflegt worden. Der letzte Commit ist zwar erst neun Monate her, hat aber lediglich den Sponsor "focsec" zur README.md und dessen Banner-PNG hinzugefügt.

Ein weiterer Blick in den Quellcode der Library zeigt, daß dort nicht die Bahn-API, sondern Web Scraping mit BeautifulSoup verwendet wird. Klar, das kann man natürlich machen, aber sobald der Betreiber einer solchen Website seinen HTML-Code ändert, funktioniert die Datenextraktion oft nicht mehr.

Sie scheint aber wesentlich komplizierter als die ursprüngliche "schiene" Library.

Dann schreib' Dir halt was zur Vereinfachung; die APIs der Bahn sind aber ein bisschen... sagen wir, unhandlich. Aber wenn Du eine langfristig benutzbare Software entwickeln willst, wirst Du um deren APIs kaum herum kommen.

[1] https://github.com/kennell/schiene

#8042651
Lesenswert?

Matthias S. schrieb:

Ein T. schrieb:

wirst Du um deren APIs kaum herum kommen

Und auch die werden alle paar Jahre geändert werden.

Wow, man merkt: da spricht der "Fachmann". Äh, nicht. Denn die benutzen diese APIs für ihre eigenen Informationssysteme und für externe Partner, die sie bei Änderungen alle gleichzeitig updaten müßten, um nichts kaputt zu machen. Darum sind die APIs natürlich versioniert, so daß veraltete Versionen der APIS auch dann weiterhin funktionieren, wenn es neue gibt. So macht man das nämlich, und die OpenAPI-Angebote der Bahn sind unhandlich, lassen aber erkennen, daß sich dort jemand viele Gedanken über Themen wie Langzeitstabilität gemacht hat.

Aber jetzt, lieber Matthias, habe ich eine Frage an Dich. Nämlich: wie kommt man dazu, was zu einem Thema zu sagen, von dem man ganz offensichtlich keine Ahnung und das man sich auch keinen Sekundenbruchteil lang angesehen hat?

#8044106
Lesenswert?

Rolf M. schrieb:

Christoph M. schrieb:

Find connections from Mannheim Hbf to Stuttgart Hbf

connections = s.connections('Berlin Hbf', 'Hannover Hbf')

Wenn du von Mannheim nach Stuttgart willst, solltest du nicht nach Verbindungen von Berlin nach Hannover suchen ;-)

PEP8: Comments that contradict the code are worse than no comments. Always make a priority of keeping the comments up-to-date when the code changes!

OP #8044109
Lesenswert?

Norbert schrieb:

PEP8: Comments that contradict the code are worse than no comments. Always make a priority of keeping the comments up-to-date when the code changes!

Noch besser: gar keine Kommentare und der Code muss so lesbar wie ein Buch sein.

Reference: "weniger schlecht programmieren" https://www.oreilly.com/library/view/weniger-schlecht-programmieren/9783955615697/

#8044168
Lesenswert?

Christoph M. schrieb:

Noch besser: gar keine Kommentare und der Code muss so lesbar wie ein Buch sein.

Findet man nur selten.

Oft gibt es eine ellenlange Lizenz am Anfang, aber überhaupt keinen Hinweis darauf, was der Code eigentlich überhaupt machen soll.

Weil jemand meinte, daß der Code ja "so leicht lesbar wie ein Buch" sei.

Einbuchstabige Variablennamen inklusive, und damit meine ich nicht i und p.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren