Sparpreise der Bahn suchen und zerstören..
.. mit Bahndit.
Problem: Wenn ich mit der Bahn von A nach B will, dies mindestens drei Tage und maximal drei Monate im Voraus weiß, gleichzeitig aber nicht an einen bestimmten Tag gebunden bin, möchte ich die günstigsten Verbindungen (lies: Sparpreise) zwischen Tag x und Tag y herausfinden.
Bisherige Lösung: Auf bahn.de suchen.
Ergebnis: Nach dem fünften Session-Timeout landet die Maus an der Wand. Was gut ist, denn so hat das sich nach Klick 8912 entwickelnde Karpaltunnelsyndrom Chancen auf Reversibilität.
Neue Lösung: Bahndit
Ein Python-Skript, das die Arbeit automatisch erledigt:
python crawlLocal.py <Abfahrtsbahnhof, volle Bhf.bezeichnung> <Zielbahnhof, volle Bhf.bezeichnung> <Erster Tag des Intervalls, in dem gesucht werden soll. Format: dd.mm.yy> <Letzter Tag des Intervalls, in dem gesucht werden soll. Format: dd.mm.yy>
Beispiel: python crawlLocal.py "Saarbruecken Hbf" "Nuernberg Hbf" 01.11.10 30.11.10
Um die Ergebnisse in eine Datei zu leiten, möchte man evtl. folgenden Command benutzen:
python crawlLocal.py von nach ab bis > ausgabe.txt
Download hier:
Installation:
Systemvoraussetzungen: Python >= 2.6 – Unter Linux ist das normalerweise vorinstalliert, unter Windows muss es nachträglich installiert werden. Die aktuelle Version findet sich unter:
http://www.python.org/download/
Wenn Python installiert ist, einfach bahndit.zip in beliebiges Verzeichnis entpacken. Anschließend Shell oder Eingabeaufforderung aufrufen und Skript starten.
Wenn die Installationsroutine unter Windows nicht von selbst die PATH-Variable erweitert, kann man das entweder von Hand tun oder man muss das Skript mit dem vollen Pfad zur python.exe aufrufen. Also:
Beispiel: C:\pythonverzeichnis\python.exe C:\bahnditverzeichnis\crawlLocal.py "Saarbruecken Hbf" "Nuernberg Hbf" 01.11.10 30.11.10
Hintergrund und Disclaimer:
Ich benutze das Skript selbst schon seit einem halben Jahr. Meines Wissens enthält es keine wesentlichen Bugs mehr, aber das Ganze ist natürlich eine zweckmäßige Quick’n'Dirty-Lösung. Deshalb: Gebrauch auf eigene Gefahr.
Was macht das Skript eigentlich genau?
Das Skript crawlt das Interface auf m.bahn.de mit den gegebenen Infos, wobei die Haltestellenauswahl unterdrückt wird (das Interface nimmt dann die nach seinem Dafürhalten ähnlichste Haltestelle an – deswegen ist es wichtig, den vollen Bahnhofsnamen zu übergeben!). Zu jeder Verbindung ermittelt es Dauer, Abfahrtszeit, Produkte (also IC, ICE..), evtl. angezeigte Sparpreise und den Normalpreis.
Die ermittelten Verbindungen werden aufsteigend nach Preis sortiert und auf stdout ausgegeben.
Bekannte Fehler:
- Das Skript prüft nicht, ob das gegebene Datum vor dem aktuellen Datum liegt – bahn.de liefert für solche Verbindungen keinen Preis zurück, wodurch es zu Fehlermeldungen kommen kann
- Der Logger ist noch nicht auf UTF8-Encoding umgestellt. Umlaute führen zwar zu Fehlermeldungen, das Programm läuft aber korrekt weiter.
- Das Skript trifft starke Annahmen über URL-Format und ausgegebener HTML-Struktur von m.bahn.de. Sobald die DB ihr Interface ändert, wird das Skript mit großer Wahrscheinlichkeit nicht mehr funktionieren / muss angepasst werden.
Sonst noch interessant:
Es liegt ein Skript bei, das Multithreading-Crawling erlaubt (RangeRetriever.py). Das erleichtert die Akquisition größerer Mengen von Verbindungen.
Further Work:
(aka Und wovon träumst du nachts? : ))
- (Web-)Interface
- Stabiler im Hinblick auf Änderungen der Website
- Intelligenter Preisagent, der auch Ländertickets und Verbundinformationen berücksichtigt
- .. idealerweise auch Flugverbindungen und Mitfahrgelegenheiten.
Credits:
- Toni für viele Diskussionen und Ideen, insbesondere unter Further Work







