#!/usr/bin/env python3 """ Parse Fähigkeitsmatrix und extrahiere vollständige Kategorisierung. """ import sys import httpx from bs4 import BeautifulSoup def parse_matrix(): """Parse die Fähigkeitsmatrix und gib CSV-Mapping aus.""" # Wiki-Login api_url = 'https://karatetrainer.net/api.php' username = 'Jinkendo' password = 'Jinkendo6970' # Synchroner Client with httpx.Client(timeout=30) as client: # Schritt 1: Login-Token holen r1 = client.get(api_url, params={ 'action': 'query', 'meta': 'tokens', 'type': 'login', 'format': 'json', }) r1.raise_for_status() data1 = r1.json() token = data1.get('query', {}).get('tokens', {}).get('logintoken', '') if not token: print("ERROR: Kein Login-Token erhalten", file=sys.stderr) return # Schritt 2: Login durchführen r2 = client.post(api_url, data={ 'action': 'login', 'lgname': username, 'lgpassword': password, 'lgtoken': token, 'format': 'json', }) r2.raise_for_status() data2 = r2.json() if data2.get('login', {}).get('result') != 'Success': print(f"ERROR: Login fehlgeschlagen: {data2}", file=sys.stderr) return # Hole Matrix-Seite als HTML page_url = 'https://karatetrainer.net/index.php?title=Fähigkeitsmatrix' r3 = client.get(page_url) r3.raise_for_status() html = r3.text if not html: print("ERROR: Konnte Matrix-HTML nicht abrufen", file=sys.stderr) return # Parse HTML soup = BeautifulSoup(html, 'html.parser') table = soup.find('table', {'class': 'wikitable'}) if not table: print("ERROR: Tabelle nicht gefunden", file=sys.stderr) return rows = table.find_all('tr') # Extrahiere Struktur # Default: KARATE Fähigkeiten (bis Row 49 wo ALLGEMEINE beginnt) current_main_cat = 'karate' current_sub_cat = None skills_data = [] for idx, row in enumerate(rows): cells = row.find_all(['td', 'th']) if len(cells) == 1: # Kategorie-Header (1 Zelle) text = cells[0].get_text(strip=True) # Überspringe Inhaltsverzeichnis (Row 4) if 'Inhaltsverzeichnis' in text: continue # Haupt-Kategorie Wechsel erkennen (nur bei "ALLGEMEINE sportliche Fähigkeiten") if 'ALLGEMEINE' in text and 'sportliche' in text: current_main_cat = 'allgemeine' current_sub_cat = None # print(f"DEBUG: Row {idx} - Wechsel zu allgemeine", file=sys.stderr) else: # Alle anderen 1-Zellen-Rows sind Unterkategorien # Bereinige Text (entferne Sonderzeichen, Leerzeichen) current_sub_cat = text.replace('­', '').strip() # soft hyphen entfernen # print(f"DEBUG: Row {idx} - Unterkategorie '{current_sub_cat}' (main_cat={current_main_cat})", file=sys.stderr) elif len(cells) == 6: # Skill-Zeile (6 Zellen: Name + 5 Level-Beschreibungen) skill_name = cells[0].get_text(strip=True).replace('­', '') # soft hyphen entfernen # Nur Skills mit Hauptkategorie UND Unterkategorie erfassen if skill_name and current_main_cat and current_sub_cat: # Fokusbereich bestimmen focus = 'karate' if current_main_cat == 'karate' else 'universal' skills_data.append({ 'skill': skill_name, 'sub_cat': current_sub_cat, 'main_cat': current_main_cat, 'focus': focus, 'row': idx }) # Duplikat-Handling: Bevorzuge spezifischere Kategorien # Bei Duplikaten: Kondition/Koordination > Kumite (für allgemeine Fähigkeiten) # Kumite > Rest (für Kampf-spezifische wie "Timing", "Antizipation") duplicates_to_remove = { ('Anaerobe Ausdauer', 'Kumite'), # Behalte Kondition ('Bewegungsschnelligkeit', 'Kumite'), # Behalte Kondition ('Flexibilität', 'Kumite'), # Behalte Kondition ('Reaktionsschnelligkeit', 'Kumite'), # Behalte Kondition ('Schnelligkeitsausdauer', 'Kumite'), # Behalte Kondition ('Antizipation', 'Koordination'), # Behalte Kumite (kampfspezifisch) ('Timing', 'Koordination'), # Behalte Kumite (kampfspezifisch) } # Filtere Duplikate filtered_skills = [] for s in skills_data: if (s['skill'], s['sub_cat']) not in duplicates_to_remove: filtered_skills.append(s) # Ausgabe als CSV (UTF-8) import sys # Force UTF-8 output sys.stdout.reconfigure(encoding='utf-8') print('skill_name,sub_category,main_category,focus_areas') for s in filtered_skills: # Escape Kommas in Namen skill = s['skill'].replace(',', ';') sub_cat = s['sub_cat'].replace(',', ';') print(f"{skill},{sub_cat},{s['main_cat']},{s['focus']}") print(f"\n# Total: {len(filtered_skills)} Skills (von {len(skills_data)} Zeilen, {len(skills_data) - len(filtered_skills)} Duplikate entfernt)", file=sys.stderr) if __name__ == '__main__': parse_matrix()