133 lines
8.3 KiB
Markdown
133 lines
8.3 KiB
Markdown
# Deutsche Bahn / Fahrplan-Datenabruf: Realität & Workarounds (2026-08-08)
|
||
|
||
Nützlich beim Bau von Reise-/Verbindungs-Websites (z.B. Zugverbindungs-Liste
|
||
urlaub.perfekt-ohne-en.de), die echte Fahrtzeiten abfragen müssen.
|
||
|
||
## Kernbefund: DB automatisiert NICHT von einem Server aus
|
||
|
||
Beim Versuch, echte deutsche Nahverkehrs-Verbindungen (RE/RB/S-Bahn) automatisiert
|
||
zu bekommen, schlugen ALLE Server-seitigen Wege fehl:
|
||
|
||
| Weg | Ergebnis |
|
||
|-----|----------|
|
||
| `https://www.bahn.de/` im **Browserbase-Browser** | ❌ **Bot-Erkennung**: Fehler 753 „Verhalten Ihres Browsers ähnelt dem eines Bots" — auch im echten Browser (stealth-Warnung: „Running WITHOUT residential proxies"). |
|
||
| DB-Web-API (`/web/api/reiseloesung`) | ❌ `OPS_BLOCKED` |
|
||
| VRR EFA (`efa.vrr.de`) | ⚠️ Funktionierte für **Verbund-Haltestellen** (Radevormwald/Remscheid), liefert aber **keine Fernziele** (Frankfurt/Hannover außerhalb des VRR-Gebiets) — nur lokale Verbunde. |
|
||
| `api.transport.rest` / GTFS | ❌ nicht erreichbar (DNS/Timeout) |
|
||
| Web-Suche (Firecrawl) | ❌ nicht konfiguriert |
|
||
|
||
**Warum es so ist:** bahn.de + DB-API betreiben aktive Anti-Bot-Abwehr, unabhängig
|
||
davon ob der Zugriff von einem Python-Skript oder einem headless-Browser kommt.
|
||
Das ist eine bewusste, dauerhafte Serverseite — kein Setup-Fehler, der sich fixen lässt.
|
||
|
||
## Funktionierende Workarounds
|
||
|
||
1. **Regionale EFA (Verbund-API) für lokale Strecken**: `https://efa.vrr.de/std3/`
|
||
(JSON via `XSLT_STOPFINDER_REQUEST` / `XSLT_TRIP_REQUEST2`) funktioniert für
|
||
Haltestellen im jeweiligen Verkehrsverbund. Nur für Nahziele im Verbund nutzen,
|
||
nicht für Fernziele.
|
||
2. **Nutzer liefert die Zeiten manuell** (bewährt): Auf bahn.de / DB-Navigator
|
||
funktioniert die Suche für **menschliche Nutzer** einwandfrei. Bei 1-2 Zielen:
|
||
Nutzer gibt die schnellste Verbindung durch ☞ Master trägt die echten Zeiten ein.
|
||
Das ist zuverlässig + kostenlos + umgeht die Bot-Sperre.
|
||
3. **Schätz-/Richtwerte mit ehrlichem Hinweis** (Standard-Fall für viele Ziele):
|
||
Wenn keine echte Verifikation möglich ist, Netzwerk-Takte/Geographie als
|
||
**Richtwert** aufführen und auf der Seite + im PDF deutlich markieren:
|
||
„vor der Fahrt gegen bahn.de/DB-Navigator prüfen". NICHT als echte Fahrzeit
|
||
ausgeben.
|
||
4. **DB-Deep-Link pro Verbindung** (Nutzer-Idee): statt die Zeiten automatisiert
|
||
zu verifizieren, einen Link auf die DB-Suche VORBEFÜLLEN, den der Nutzer in
|
||
seinem Browser öffnet. Da der Nutzer keine Bot-Sperre hat, sieht er dort die
|
||
echten aktuellen Zeiten.
|
||
|
||
⚠️ **WICHTIG — LIVE-VERIFIZIERT am 2026-08-08 (Muss über den früheren Stand):
|
||
Die Deutsche Bahn bietet 2026 KEIN stabiles URL-Deep-Link-Format mehr an.**
|
||
Alle vorher als „stabil" geltenden Schemata sind empirisch tot:
|
||
- ❌ `reiseauskunft.bahn.de/bin/query.exe/dn?...` → **toter DNS** (`DNS_PROBE_FINISHED_NXDOMAIN`), Domain existiert nicht mehr.
|
||
- ❌ `reiseauskunft.de/bin/query.exe/...` → toter Pfad („Seite existiert nicht mehr").
|
||
- ❌ `www.bahn.de/buchung/fahrplan/suche?...` mit Query-Parametern → DB-SPA übernimmt die Eingaben NICHT (zeigt nur leere Suchseite).
|
||
- ❌ `www.bahn.de/buchung/fahrplan/suche#query=start:…;destination:…` → undokumentierte interne SPA-Fragmentroute, bricht (Einträge werden nicht übernommen, nur Fehlermeldung → leere Suche).
|
||
|
||
✅ **Funktionierende, ehrliche Lösung 2026-08-08:** Ein einfacher, zuverlässiger
|
||
Link auf die **noch erreichbare Sucheseite** `https://www.bahn.de/buchung/fahrplan/suche`
|
||
auf einer Zwischenseite, die Start+Ziel (readonly) anzeigt + einen Button
|
||
„In DB-Suche öffnen" (neuer Tab) + Fallback-Link. Der Nutzer tippt Start/Ziel
|
||
dort manuell ein (10 Sekunden) — aber der Link landet garantiert auf einer
|
||
funktonierenden Seite statt auf einem Deadlink. **Verifiziere jede DB-URL mit
|
||
`curl -s -o /dev/null -w "%{http_code}"` VOR dem Einsatz** — Sub-Agenten-Reviews
|
||
können veraltete Formate als „korrekt/getestet" bestätigen, ohne es live geprüft
|
||
zu haben (passiert hier real). Eine muntere Vorbefüllung ist 2026 nicht mehr
|
||
zuverlässig möglich; wer sie trotzdem versucht, scheitert an der SPA.
|
||
|
||
⚠️ Die offizielle DB-API (api.deutschebahn.com) wäre die robusteste Quelle für
|
||
programmatische Zeiten, braucht aber einen API-Key — und ist weiterhin
|
||
vorbehaltlich Bot/Key-Zugang zu prüfen.
|
||
|
||
## Google Maps als ÖPNV-Quelle? NEIN — ICE lässt sich nicht rausfiltern (2026-08-08)
|
||
|
||
Nutzer-Idee beim Bau einer Verbindungs-Site: „Kann man Google Maps-Öffis-Daten
|
||
nehmen?" — ehrliche Antwort, die in Zukunft nicht neu hergeleitet werden muss:
|
||
|
||
- Google Maps **zeigt** ÖPNV (Bus, S-Bahn, RE, ICE, IC), aber als schnellste Route
|
||
schlägt es **standardmäßig ICE/IC vor**.
|
||
- Es gibt **KEINEN sauberen „nur Regionalverkehr / Deutschlandticket"-Filter** in
|
||
Google Maps (nur ein grober Transit-Filter). `regional-only` von ICE zu trennen
|
||
ist nicht zuverlässig möglich.
|
||
- Dieselben GTFS-Fahrpläne wie überall (DB/Verkehrsverbünde) — also nichts Besseres
|
||
/qchlechteres als reiseauskunft.
|
||
- Google Maps blockt zudem Bots (wie die DB), sodass saubere Automatisierung nicht
|
||
klappt.
|
||
- **Fazit:** Für eine „kein ICE / nur Deutschlandticket“-Anforderung ist unser
|
||
DB-Deep-Link zur noch erreichbaren Sucheseite (`https://www.bahn.de/buchung/fahrplan/suche`,
|
||
ohne Vorbefüllung, siehe Abschnitt 4) besser — die Seite hat einen expliziten
|
||
Deutschlandticket-Filter, den der Nutzer einen Klick entfernt sieht. (Der früher
|
||
genannte `query.exe/dn`-Deep-Link ist tot — siehe Abschnitt 4.)
|
||
|
||
## Label nach ECHTER Fahrtzeit, nicht nach Wunsch-Kategorie (2026-08-08)
|
||
|
||
Nutzer: „Nicht EINE Fahrt 5-7h in der Liste, ich sehe nur <5h oder >7h." Ursache war
|
||
**zweifach**, beides wartbar:
|
||
|
||
1. **Label-Mismatch-Bug:** 168 Ebene-2-Zeilen waren als `Kernziel (5-7h)` markiert,
|
||
obwohl ihre Fahrtzeiten real 0,3–4h waren. Beim Seeden wird gern „5-7h" als Wunsch-Category
|
||
an die Fernziele gehängt. **Fix: Kategorie aus der echten Fahrtzeit ableiten**
|
||
(Parser `~h` → float, dann `<5 → unter 5h`, `5–7 → Kernziel (5-7h)`, `>7 → über 7h`),
|
||
nicht als Design-Wunsch beim INSERT setzen.
|
||
2. **Geographische Realität:** per reinem Nahverkehr sind echte 5–7h-Ziele selten
|
||
(viele Großstädte entweder <3h Nahzone oder >8h Fernzone). Das ist kein Bug,
|
||
sondern Physik — die Seite soll alle Kategorien ehrlich anzeigen und „5-7h" nur
|
||
dort führen, wo es sie wirklich gibt (ab weiter südlich/östlich gelegenen Städten:
|
||
Frankfurt→München/Dresden, Hannover→Stuttgart etc.).
|
||
|
||
## Ehrlichkeits-Regel (Nutzer erwartet dies)
|
||
|
||
- Niemals fabrizierte „fahrhatige" Verbindungen oder konkrete Uhrzeiten als real
|
||
ausgeben, wenn sie nur geschätzt sind.
|
||
- Schätzwerte IMMER als Bereich (`~5-5,5 h`) + mit Verweis auf bahn.de labeln.
|
||
|
||
## RAPTOR statt Dijkstra für echte GTFS-Routing (2026-08-19, Team-Unraid)
|
||
|
||
Für GTFS-Verbindungssuche auf großen Knoten ist **einfacher Dijkstra instabil** —
|
||
bei benachbarten Zielen kamen absurde Differenzen (Mainz→Berlin 11h vs. Nachbar
|
||
Wiesbaden 3h). Standard-Lösung ist **RAPTOR** (Round-Based Public Transit Optimized
|
||
Route): erweitert die Reichweite Runde um Runde über echte Trips und behandelt
|
||
"Zug nehmen → aussteigen → umsteigen" natürlich, statt auf einem statischen
|
||
Graphen zu kürzen.
|
||
|
||
- **Stop-Mehrdeutigkeit** (ein Bahnhof, mehrere stop_ids, nur 1 aktiv in `st`) →
|
||
eindeutig über `parent_station`/Geo-Mapping auflösen.
|
||
- **Umstiegsbuffer** (4 min) + sauberes Ziel-Stop-Matching verhindern die
|
||
"benachbarte Ziele, extrem abweichende Zeiten"-Inkonsistenz.
|
||
- Verifizieren mit Plausibilitäts-Ankern (z.B. Trier→Saarbrücken ~1h, Köln→Aachen
|
||
~50min) — nie den Algorithmus blind vertrauen.
|
||
- Wenn der Nutzer einen Konkreten echten Wert liefert (z.B. „Trier 6h"), ihn
|
||
bevorzugt übernehmen statt der Schätzung.
|
||
|
||
## Fakten zur Ziel-Menge (Zugverbindungs-Website, Kontext)
|
||
|
||
- Schwelle kann variieren (250k → 100k Einwohner → weit mehr Ziele, ~33 in dieser Site).
|
||
- Reichweite per **reinem Nahverkehr** (kein ICE) ab Bergisch-Land/Ruhrgebiet:
|
||
die meisten Großstädte sind entweder **<3h** (Nahzone: Köln, Düsseldorf, Ruhrgebiet)
|
||
oder **>8h** (Fernzone: Berlin, München). Echte **5–7h**-Ziele sind selten — das sind
|
||
genau die Grenzfälle (Frankfurt ~5h, Wiesbaden ~5,5h, Hannover ~5,5–6,5h, Kassel ~6,5–7h).
|
||
Regional-Agenten (SwitchHermes/LaptopHermes) lieferten dazu gute Geographie-Analysen. |