From 34320b46d9ee5dbf13aadc39960a73c0b3eb0eb5 Mon Sep 17 00:00:00 2001 From: Lars Date: Mon, 11 Aug 2025 15:33:15 +0200 Subject: [PATCH] scripts/wiki_importer.py aktualisiert --- scripts/wiki_importer.py | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/scripts/wiki_importer.py b/scripts/wiki_importer.py index d541fd4..47b2c1a 100644 --- a/scripts/wiki_importer.py +++ b/scripts/wiki_importer.py @@ -1,14 +1,16 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- """ -wiki_importer.py – v2.3.6 +wiki_importer.py – v2.3.7 -Fixes ggü. v2.3.5: -- **Equipment**: eigenes Template `{{Hilfsmittel}}` wird jetzt ausgewertet → `equipment` wird gesetzt. -- **Keywords**: Synonyme bleiben; zusätzlich kleine Robustheit für ungewöhnliche Schreibungen. -- **imported_at**: wird nun **sowohl bei UPDATE als auch bei CREATE** gesetzt, damit das Feld immer gefüllt ist. +Fixes ggü. v2.3.6: +- **Keywords/EQUIPMENT/DISCIPLINE u.a. wurden teils nicht erkannt**: Bugfix in `_get_first()` – + Kandidatenschlüssel werden jetzt ebenfalls normalisiert (`_norm_key(c)`), damit + `Schlüsselworte` (aus dem Wiki) zuverlässig matcht. +- `_get_first_fuzzy()` normalisiert die Such-Tokens. +- Kleine Bugfixes/Polish: `action.upper()` im Dry-Run, sanftere Keywords-Splittung. -Keine API-/CLI-Änderungen. +Hinweis: Keine API-/CLI-Änderungen. Parser unterstützt weiterhin `{{Hilfsmittel}}`. """ import os @@ -54,9 +56,9 @@ def _norm_tpl(s: str) -> str: TPL_UEBUNG_INFOBOX = {"ubunginfobox", "uebunginfobox", "ubunginfo", "uebunginfo"} TPL_UEBUNGSBESCHREIBUNG = {"ubungsbeschreibung", "uebungsbeschreibung", "beschreibungubung", "beschreibunguebung"} TPL_SKILLDEV = {"skilldevelopment"} -TPL_HILFSMITTEL = {"hilfsmittel"} # << NEU +TPL_HILFSMITTEL = {"hilfsmittel"} -# Synonyme für Parameter (normalisierte Keys via _norm_key) +# Synonyme (werden im Code nochmals normalisiert) KEYS_SUMMARY = ["summary", "kurzbeschreibung", "beschreibung", "kurztext"] KEYS_EXECUTION = ["durchführung", "durchfuehrung", "ausführung", "ausfuehrung", "execution", "ablauf", "vorgehen"] KEYS_DURATION = ["dauer", "zeit", "dauer_minuten", "dauer (min)", "minuten"] @@ -138,7 +140,7 @@ def parse_exercise(title: str, pageid: int) -> Dict[str, Any]: lvl_i = 0 if cap: raw["capabilities"].append({"capability": cap, "level": lvl_i}) - elif name_norm in TPL_HILFSMITTEL: # << NEU: Template für Ausrüstung + elif name_norm in TPL_HILFSMITTEL: for p in tpl.params: raw[str(p.name).strip()] = str(p.value).strip() @@ -170,7 +172,7 @@ def _canon_title(t: str) -> str: def compute_fingerprint(payload: Dict[str, Any]) -> str: kws = payload.get("keywords") or [] - # robust gegen Strichvarianten und Doppelkommas + # Strichvarianten normalisieren kws = [k.replace("\u2013", "-").replace("\u2014", "-") for k in kws] kws = sorted({(k or "").strip() for k in kws if (k or "").strip()}, key=str.casefold) dur = payload.get("duration_minutes") or 0 @@ -198,17 +200,18 @@ def _norm_keymap(d: Dict[str, Any]) -> Dict[str, Any]: def _get_first(d: Dict[str, Any], candidates: List[str]) -> Any: m = _norm_keymap(d) for c in candidates: - v = m.get(c) + v = m.get(_norm_key(c)) # << Bugfix: Kandidaten ebenfalls normalisieren if v not in (None, ""): return v return None def _get_first_fuzzy(d: Dict[str, Any], tokens: List[str]) -> Any: m = _norm_keymap(d) + toks = [_norm_key(t) for t in tokens] for k, v in m.items(): if v in (None, ""): continue - if all(t in k for t in tokens): + if all(t in k for t in toks): return v return None @@ -246,7 +249,7 @@ def build_payload(raw: Dict[str, Any], fullurl: str, category: str, *, mutate: b kw_raw = _get_first_fuzzy(raw, ["stich", "worte"]) or _get_first_fuzzy(raw, ["schlag", "worte"]) or "" keywords: List[str] = [] if isinstance(kw_raw, str): - # robuste Auftrennung; ignoriert doppelte Kommas u. ä. + # robuste Auftrennung; ignoriert doppelte Kommas/Zeilenumbrüche parts = [p.strip() for p in kw_raw.replace("\n", ",").split(",")] keywords = [p for p in parts if p] @@ -389,14 +392,14 @@ def upsert_exercise(payload: Dict[str, Any], *, dry_run: bool = False) -> str: action, reason = "create", "unexpected lookup type" if dry_run: - print(f"[DryRun] {action.UPPER():6} '{title}' ({ext_id}) – {reason}") + print(f"[DryRun] {action.upper():6} '{title}' ({ext_id}) – {reason}") if action == "update": _print_diff(found_payload, payload) return action if action == "create": payload2 = dict(payload) - payload2["imported_at"] = _now_iso() # << immer setzen + payload2["imported_at"] = _now_iso() resp = requests.post(EXERCISE_API, json=payload2, timeout=REQUEST_TIMEOUT) if resp.status_code == 422: print(f"[Create] '{title}' -> FAILED 422:\n{resp.text}") @@ -409,7 +412,7 @@ def upsert_exercise(payload: Dict[str, Any], *, dry_run: bool = False) -> str: print(f"[Create] '{title}' – {reason} -> OK") elif action == "update": payload2 = dict(payload) - payload2["imported_at"] = _now_iso() # << setzen bei Update + payload2["imported_at"] = _now_iso() resp = requests.post(EXERCISE_API, json=payload2, timeout=REQUEST_TIMEOUT) if resp.status_code == 422: print(f"[Update] '{title}' -> FAILED 422:\n{resp.text}")