diff --git a/brancheneinstufung.py b/brancheneinstufung.py index 413012101..facc051d7 100644 --- a/brancheneinstufung.py +++ b/brancheneinstufung.py @@ -109,29 +109,42 @@ PATTERNS_FILE_TXT = "technician_patterns.txt" # Alt (Optional beibehalten) PATTERNS_FILE_JSON = "technician_patterns.json" # Neu (Empfohlen) def load_branch_mapping(file_path='Branchen.csv'): + """ + Lädt das Mapping von Detail-Branche zu Branchen-Gruppe aus einer CSV-Datei. + Ist extrem robust gegen Kodierungs-, Spaltennamen- und Pfad-Fehler. + """ logger = logging.getLogger(__name__) absolute_path = os.path.abspath(file_path) - logger.info(f"Versuche Branchen-Mapping zu laden von: '{absolute_path}'") + logger.info(f"Lade Branchen-Mapping von: '{absolute_path}'") + if not os.path.exists(file_path): - logger.error(f"DATEI NICHT GEFUNDEN an Pfad: '{absolute_path}'") + logger.error(f"DATEI NICHT GEFUNDEN: '{absolute_path}'. Branchen-Mapping wird leer sein.") return {} try: + # encoding='utf-8-sig' behandelt das BOM-Problem. df_mapping = pd.read_csv(file_path, sep=';', encoding='utf-8-sig') - logger.info(f"Datei '{file_path}' erfolgreich mit pandas gelesen. {len(df_mapping)} Zeilen gefunden.") - df_mapping.columns = [str(col).strip() for col in df_mapping.columns] + logger.info(f"Datei '{file_path}' gelesen. {len(df_mapping)} Zeilen gefunden.") + # Bereinige ALLE Spaltennamen von Leerzeichen und unsichtbaren Zeichen + original_columns = list(df_mapping.columns) + df_mapping.columns = [str(col).strip() for col in original_columns] + + # Prüfe, ob die bereinigten Spaltennamen sich von den Originalen unterscheiden + if original_columns != list(df_mapping.columns): + logger.warning(f"Spaltennamen wurden bereinigt. Original: {original_columns} -> Neu: {list(df_mapping.columns)}") + + # Harte Überprüfung der erwarteten Spaltennamen expected_cols = ['Branch Group', 'Branch'] if not all(col in df_mapping.columns for col in expected_cols): - logger.error(f"FEHLER: Erwartete Spalten {expected_cols} in '{file_path}' nicht gefunden. Gefundene Spalten: {list(df_mapping.columns)}") + logger.error(f"FEHLER: Die erwarteten Spalten {expected_cols} wurden in '{file_path}' nicht gefunden. " + f"Gefundene Spalten nach Bereinigung: {list(df_mapping.columns)}. Branchen-Mapping wird leer sein.") return {} + # Normalisierte Keys erstellen df_mapping['normalized_keys'] = df_mapping['Branch'].apply(normalize_for_mapping) - if df_mapping['normalized_keys'].duplicated().any(): - duplicates = df_mapping[df_mapping['normalized_keys'].duplicated()]['normalized_keys'] - logger.warning(f"WARNUNG: Duplikate in normalisierten Branchen-Keys gefunden! Dies kann zu inkonsistentem Mapping führen. Duplikate: {list(duplicates)}") - + # Dictionary erstellen branch_map_dict = pd.Series( df_mapping['Branch Group'].str.strip().values, index=df_mapping['normalized_keys'] @@ -140,8 +153,8 @@ def load_branch_mapping(file_path='Branchen.csv'): logger.info(f"Branchen-Mapping aus '{file_path}' erfolgreich geladen ({len(branch_map_dict)} Einträge).") return branch_map_dict - except Exception as e: - logger.error(f"FATALER FEHLER beim Laden oder Verarbeiten der Branchen-Mapping-Datei '{file_path}':") + except Exception: + logger.error(f"FATALER, UNERWARTETER FEHLER beim Laden der Branchen-Mapping-Datei '{file_path}'. Branchen-Mapping wird leer sein.") logger.error(traceback.format_exc()) return {} @@ -165,7 +178,7 @@ class Config: HTML_PARSER = "html.parser" # Parser fuer BeautifulSoup ('lxml' ist schneller, erfordert aber Installation) TOKEN_MODEL = "gpt-3.5-turbo" # OpenAI Modell fuer Token-Zaehlung/Chat (Standard fuer die meisten Calls) USER_AGENT = 'Mozilla/5.0 (compatible; UnternehmenSkript/1.0; +https://www.example.com/bot)' # User-Agent fuer Web Scraping/Requests (Beispiel URL anpassen) - BRANCH_MAPPING = load_branch_mapping() + #BRANCH_MAPPING = load_branch_mapping() # --- Konfiguration fuer Batching & Parallelisierung --- # Passen Sie diese Werte an die Leistung Ihres Systems und die API-Limits an. @@ -10261,6 +10274,9 @@ def main(): # handlers=[] verhindert default Console Handler, wir fuegen ihn manuell hinzu fuer mehr Kontrolle logging.basicConfig(level=log_level, format=log_format, handlers=[]) # log_format wird hier bereits verwendet + ZIEL_BRANCHENSCHEMA, FOKUS_BRANCHEN = load_target_schema() + BRANCH_MAPPING = load_branch_mapping() + # Console Handler explizit hinzufuegen console_handler = logging.StreamHandler() console_handler.setLevel(log_level) # Nimm das globale Level