mgokg commited on
Commit
728e272
·
verified ·
1 Parent(s): 2c877f9

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +69 -41
app.py CHANGED
@@ -1,13 +1,17 @@
 
1
  import requests
2
- import xml.etree.ElementTree as ET
3
  from datetime import datetime, timedelta
 
4
  import json
5
 
6
  def get_station_info(pattern, client_id, api_key):
7
- """Ermittelt EVA-Nummer und Namen für einen Suchbegriff."""
8
  url = f"https://apis.deutschebahn.com/db-api-marketplace/apis/timetables/v1/station/{pattern}"
9
- headers = {'DB-Client-Id': client_id, 'DB-Api-Key': api_key, 'accept': 'application/xml'}
10
-
 
 
 
11
  try:
12
  response = requests.get(url, headers=headers, timeout=10)
13
  response.raise_for_status()
@@ -20,10 +24,13 @@ def get_station_info(pattern, client_id, api_key):
20
  return None
21
 
22
  def fetch_timetable_hour(eva, date_str, hour_str, client_id, api_key):
23
- """Hilt den Fahrplan für eine spezifische Stunde."""
24
  url = f"https://apis.deutschebahn.com/db-api-marketplace/apis/timetables/v1/plan/{eva}/{date_str}/{hour_str}"
25
- headers = {'DB-Client-Id': client_id, 'DB-Api-Key': api_key, 'accept': 'application/xml'}
26
-
 
 
 
27
  try:
28
  response = requests.get(url, headers=headers, timeout=10)
29
  if response.status_code == 200:
@@ -32,72 +39,93 @@ def fetch_timetable_hour(eva, date_str, hour_str, client_id, api_key):
32
  pass
33
  return None
34
 
35
- def get_next_connections_json(departure_name, destination_name, client_id, api_key):
36
- """Sucht die nächsten 3 Verbindungen und gibt sie als JSON zurück."""
37
 
38
- # 1. Stationen auflösen
39
- dep_info = get_station_info(departure_name, client_id, api_key)
40
- dest_info = get_station_info(destination_name, client_id, api_key)
 
 
 
41
 
42
- if not dep_info or not dest_info:
43
- return json.dumps({"error": "Station nicht gefunden"}, indent=4)
44
 
45
- # 2. Zeitstempel vorbereiten
46
  now = datetime.now()
47
- all_found_connections = []
48
 
49
- # Wir prüfen die aktuelle und die nächste Stunde, um sicherzugehen, dass wir 3 finden
50
- for hour_offset in range(2):
51
  search_time = now + timedelta(hours=hour_offset)
52
  datum = search_time.strftime("%y%m%d")
53
  stunde = search_time.strftime("%H")
54
 
55
  root = fetch_timetable_hour(dep_info['eva'], datum, stunde, client_id, api_key)
56
- if root is None:
57
- continue
58
 
59
  for train in root.findall('.//s'):
60
  dp = train.find('dp')
61
  if dp is None: continue
62
 
63
- # Prüfen ob Ziel im Pfad
64
  path = dp.get('ppth', '')
65
- if dest_info['name'].lower() in path.lower() or destination_name.lower() in path.lower():
66
 
67
- # Zeit-Parsing (Format: YYMMDDHHMM)
68
- pt = dp.get('pt', '')
69
  if not pt: continue
70
 
71
- # In datetime Objekt umwandeln für Vergleich und Sortierung
72
  dep_dt = datetime.strptime(pt, "%y%m%d%H%M")
73
 
74
- # Nur Züge in der Zukunft berücksichtigen
75
  if dep_dt >= now:
76
- all_found_connections.append({
 
77
  "startort": dep_info['name'],
78
  "zielort": dest_info['name'],
79
  "abfahrtszeit": dep_dt.strftime("%d.%m.%Y %H:%M"),
80
  "gleis": dp.get('pp', 'n/a'),
81
- "zug": f"{train.find('tl').get('c')} {train.find('tl').get('n')}",
82
- "_dt": dep_dt # Intern für Sortierung
83
  })
84
 
85
- # 3. Sortieren nach Zeit und Top 3 extrahieren
86
- all_found_connections.sort(key=lambda x: x['_dt'])
87
 
88
- # Entferne internes Hilfsfeld _dt und limitiere auf 3
89
- final_list = []
90
- for c in all_found_connections[:3]:
91
- del c['_dt']
92
- final_list.append(c)
 
 
 
 
 
93
 
94
- return json.dumps(final_list, indent=4, ensure_ascii=False)
 
 
95
 
96
- # --- Beispielaufruf ---
97
- # client_id = "DEINE_ID"
98
- # api_key = "DEIN_KEY"
99
- # print(get_next_connections_json("Frankfurt Hbf", "Berlin", client_id, api_key))
 
 
 
 
 
 
 
 
 
 
 
 
100
 
 
 
101
 
102
  """
103
  import gradio as gr
 
1
+ import gradio as gr
2
  import requests
 
3
  from datetime import datetime, timedelta
4
+ import xml.etree.ElementTree as ET
5
  import json
6
 
7
  def get_station_info(pattern, client_id, api_key):
8
+ """Ermittelt EVA-Nummer und offiziellen Namen."""
9
  url = f"https://apis.deutschebahn.com/db-api-marketplace/apis/timetables/v1/station/{pattern}"
10
+ headers = {
11
+ 'DB-Client-Id': client_id,
12
+ 'DB-Api-Key': api_key,
13
+ 'accept': 'application/xml'
14
+ }
15
  try:
16
  response = requests.get(url, headers=headers, timeout=10)
17
  response.raise_for_status()
 
24
  return None
25
 
26
  def fetch_timetable_hour(eva, date_str, hour_str, client_id, api_key):
27
+ """Ruft den Fahrplan für eine bestimmte Stunde ab."""
28
  url = f"https://apis.deutschebahn.com/db-api-marketplace/apis/timetables/v1/plan/{eva}/{date_str}/{hour_str}"
29
+ headers = {
30
+ 'DB-Client-Id': client_id,
31
+ 'DB-Api-Key': api_key,
32
+ 'accept': 'application/xml'
33
+ }
34
  try:
35
  response = requests.get(url, headers=headers, timeout=10)
36
  if response.status_code == 200:
 
39
  pass
40
  return None
41
 
42
+ def search_next_3_connections(departure, destination, client_id, api_key):
43
+ """Hauptfunktion: Findet die nächsten 3 Verbindungen ab 'jetzt'."""
44
 
45
+ if not all([departure, destination, client_id, api_key]):
46
+ return {"error": "Bitte alle Felder ausfüllen."}
47
+
48
+ # 1. IBNRs ermitteln
49
+ dep_info = get_station_info(departure, client_id, api_key)
50
+ dest_info = get_station_info(destination, client_id, api_key)
51
 
52
+ if not dep_info: return {"error": f"Startort '{departure}' nicht gefunden."}
53
+ if not dest_info: return {"error": f"Zielort '{destination}' nicht gefunden."}
54
 
 
55
  now = datetime.now()
56
+ found_connections = []
57
 
58
+ # 2. Suche in der aktuellen und der nächsten Stunde (um 3 Verbindungen zu garantieren)
59
+ for hour_offset in range(3): # Wir schauen bis zu 2 Stunden voraus
60
  search_time = now + timedelta(hours=hour_offset)
61
  datum = search_time.strftime("%y%m%d")
62
  stunde = search_time.strftime("%H")
63
 
64
  root = fetch_timetable_hour(dep_info['eva'], datum, stunde, client_id, api_key)
65
+ if root is None: continue
 
66
 
67
  for train in root.findall('.//s'):
68
  dp = train.find('dp')
69
  if dp is None: continue
70
 
71
+ # Prüfen ob Ziel im geplanten Pfad (ppth)
72
  path = dp.get('ppth', '')
73
+ if dest_info['name'].lower() in path.lower() or destination.lower() in path.lower():
74
 
75
+ pt = dp.get('pt', '') # Geplante Zeit: YYMMDDHHMM
 
76
  if not pt: continue
77
 
 
78
  dep_dt = datetime.strptime(pt, "%y%m%d%H%M")
79
 
80
+ # Nur Verbindungen in der Zukunft (ab Zeitstempel jetzt)
81
  if dep_dt >= now:
82
+ tl = train.find('tl')
83
+ found_connections.append({
84
  "startort": dep_info['name'],
85
  "zielort": dest_info['name'],
86
  "abfahrtszeit": dep_dt.strftime("%d.%m.%Y %H:%M"),
87
  "gleis": dp.get('pp', 'n/a'),
88
+ "zug": f"{tl.get('c', '')} {tl.get('n', '')}",
89
+ "_dt": dep_dt # Hilfsfeld zum Sortieren
90
  })
91
 
92
+ # 3. Sortieren und Top 3 auswählen
93
+ found_connections.sort(key=lambda x: x['_dt'])
94
 
95
+ # Bereinigen der Ergebnisse für die JSON-Ausgabe
96
+ final_results = []
97
+ for c in found_connections[:3]:
98
+ # Entferne das interne Datetime-Objekt vor der JSON-Konvertierung
99
+ res = {k: v for k, v in c.items() if k != "_dt"}
100
+ final_results.append(res)
101
+
102
+ return final_results
103
+
104
+ # --- Gradio UI ---
105
 
106
+ def ui_wrapper(dep, dest, cid, akey):
107
+ results = search_next_3_connections(dep, dest, cid, akey)
108
+ return json.dumps(results, indent=4, ensure_ascii=False)
109
 
110
+ with gr.Blocks(title="DB JSON Fahrplan", theme=gr.themes.Soft()) as demo:
111
+ gr.Markdown("# 🚆 DB Verbindungs-Suche (JSON)")
112
+ gr.Markdown("Ermittelt die nächsten 3 Verbindungen ab dem aktuellen Zeitstempel.")
113
+
114
+ with gr.Row():
115
+ cid_input = gr.Textbox(label="DB Client ID", type="password")
116
+ akey_input = gr.Textbox(label="DB API Key", type="password")
117
+
118
+ with gr.Row():
119
+ dep_input = gr.Textbox(label="Abfahrtsort", placeholder="z.B. Berlin")
120
+ dest_input = gr.Textbox(label="Zielort", placeholder="z.B. Hamburg")
121
+
122
+ btn = gr.Button("Suchen", variant="primary")
123
+ output = gr.JSON(label="JSON Ergebnis") # Nutzt Gradio JSON Komponente für schöneres Format
124
+
125
+ btn.click(fn=ui_wrapper, inputs=[dep_input, dest_input, cid_input, akey_input], outputs=output)
126
 
127
+ if __name__ == "__main__":
128
+ demo.launch()
129
 
130
  """
131
  import gradio as gr