diff --git a/brancheneinstufung.py b/brancheneinstufung.py index fba43f09..4ae52301 100644 --- a/brancheneinstufung.py +++ b/brancheneinstufung.py @@ -2012,22 +2012,20 @@ def _process_batch(sheet, batches, row_numbers): def process_verification_only(sheet_handler, start_row_index_in_sheet, end_row_index_in_sheet): """ - Batch-Prozess nur für Wikipedia-Verifizierung. - Prüft für jede Zeile im Bereich, ob Timestamp AN bereits gesetzt ist. + Batch-Prozess nur für Wikipedia-Verifizierung. Verarbeitet ALLE Zeilen im + angegebenen Bereich und setzt den AN-Timestamp. """ debug_print(f"Starte Wikipedia-Verifizierungsmodus (Batch) für Zeilen {start_row_index_in_sheet} bis {end_row_index_in_sheet}...") - # Lade aktuelle Daten direkt hier all_data = sheet_handler.get_all_data_with_headers() - if not all_data or len(all_data) <= 5: # Check ob Daten vorhanden sind + if not all_data or len(all_data) <= 5: debug_print("FEHLER/WARNUNG: Keine Daten zum Verarbeiten in process_verification_only gefunden.") return # Hole Index für AN Timestamp timestamp_col_key = "Wikipedia Timestamp" timestamp_col_index = COLUMN_MAP.get(timestamp_col_key) - ts_col_letter = sheet_handler._get_col_letter(timestamp_col_index + 1) if timestamp_col_index is not None else "FEHLER" - + ts_col_letter = sheet_handler._get_col_letter(timestamp_col_index + 1) if timestamp_col_index is not None else "AN_FEHLER" if timestamp_col_index is None: debug_print(f"FEHLER: Spaltenschlüssel '{timestamp_col_key}' nicht in COLUMN_MAP gefunden. Breche Wiki-Verifizierung ab.") @@ -2037,7 +2035,7 @@ def process_verification_only(sheet_handler, start_row_index_in_sheet, end_row_i current_batch = [] current_row_numbers = [] processed_count = 0 - skipped_count = 0 + # skipped_count nicht mehr benötigt for i in range(start_row_index_in_sheet, end_row_index_in_sheet + 1): row_index_in_list = i - 1 @@ -2047,27 +2045,9 @@ def process_verification_only(sheet_handler, start_row_index_in_sheet, end_row_i row = all_data[row_index_in_list] - # --- DEBUGGING Timestamp-Prüfung AN --- - ts_value_an = "INDEX_FEHLER" - ts_an_is_set = False - if len(row) > timestamp_col_index: - ts_value_an = row[timestamp_col_index] - ts_an_is_set = bool(str(ts_value_an).strip()) # Prüfe, ob Wert nach strip nicht leer ist - # Logge für die ersten 5 geprüften und letzte 5 geprüfte Zeilen im Range, oder wenn es sich ändert - log_debug = (i < start_row_index_in_sheet + 5 or i > end_row_index_in_sheet - 5 or i % 500 == 0) - if log_debug: - debug_print(f"Zeile {i} (Wiki Check): Prüfe Timestamp {ts_col_letter} (Index {timestamp_col_index}). Rohwert='{ts_value_an}', Strip='{str(ts_value_an).strip()}', Bedingung ist: {ts_an_is_set}") - # --- Ende DEBUGGING --- + # --- KEINE Timestamp-Prüfung mehr hier --- - if ts_an_is_set: - # Weniger Lärm im Log, nur zählen - skipped_count += 1 - if skipped_count == 1 or skipped_count % 100 == 0: # Logge den ersten und jeden 100. übersprungenen - debug_print(f"Zeile {i}: Überspringe Wiki-Verifizierung (Timestamp {ts_col_letter} vorhanden: '{ts_value_an.strip()}'). ({skipped_count} gesamt übersprungen)") - continue - # --- Ende Timestamp-Prüfung --- - - # (Restliche Logik zum Erstellen von entry_text wie zuvor) + # Erstelle Text für den Prompt (wie zuvor) company_name = row[COLUMN_MAP["CRM Name"]] if len(row) > COLUMN_MAP["CRM Name"] else '' crm_desc = row[COLUMN_MAP["CRM Beschreibung"]] if len(row) > COLUMN_MAP["CRM Beschreibung"] else '' wiki_url = row[COLUMN_MAP["Wiki URL"]] if len(row) > COLUMN_MAP["Wiki URL"] and row[COLUMN_MAP["Wiki URL"]].strip() not in ['', 'k.A.'] else 'k.A.' @@ -2089,11 +2069,13 @@ def process_verification_only(sheet_handler, start_row_index_in_sheet, end_row_i # Wenn Batch voll oder letzte Zeile erreicht if len(current_batch) >= batch_size or i == end_row_index_in_sheet: if current_batch: - # Setze zuerst den AN Timestamp für die bearbeiteten Zeilen + # Rufe _process_batch auf, das S-Y schreibt + _process_batch(sheet_handler.sheet, current_batch, current_row_numbers) + + # Setze den AN Timestamp für die bearbeiteten Zeilen *nach* dem Batch wiki_ts_updates = [] current_wiki_timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") for row_num in current_row_numbers: - # Verwende Spaltenbuchstaben dynamisch wiki_ts_updates.append({'range': f'{ts_col_letter}{row_num}', 'values': [[current_wiki_timestamp]]}) if wiki_ts_updates: @@ -2103,14 +2085,12 @@ def process_verification_only(sheet_handler, start_row_index_in_sheet, end_row_i else: debug_print(f"FEHLER beim Setzen des Wiki-Timestamps {ts_col_letter} für Batch.") - # Rufe dann _process_batch auf, das S-Y schreibt - _process_batch(sheet_handler.sheet, current_batch, current_row_numbers) - time.sleep(Config.RETRY_DELAY) # Pause nach API Calls + time.sleep(Config.RETRY_DELAY) # Pause nach API Calls und Sheet Update current_batch = [] current_row_numbers = [] - debug_print(f"Wikipedia-Verifizierungs-Batch abgeschlossen. {processed_count} Zeilen zur Verarbeitung an ChatGPT gesendet, {skipped_count} Zeilen übersprungen.") + debug_print(f"Wikipedia-Verifizierungs-Batch abgeschlossen. {processed_count} Zeilen verarbeitet.") # Anpassung in _process_batch: Setzt jetzt *nicht* mehr AO/AP, sondern nur S-Y def _process_batch(sheet, batches, row_numbers): @@ -2208,15 +2188,24 @@ def _process_batch(sheet, batches, row_numbers): # Komplette Funktion process_website_batch (prüft jetzt Timestamp AT mit erzwungenem Debugging) def process_website_batch(sheet_handler, start_row_index_in_sheet, end_row_index_in_sheet): - """Batch-Prozess für Website-Scraping (Rohtext & Zusammenfassung).""" + """ + Batch-Prozess für Website-Scraping (Rohtext & Zusammenfassung). + Verarbeitet ALLE Zeilen im angegebenen Bereich und setzt AT + AP Timestamps. + """ debug_print(f"Starte Website-Scraping (Batch) für Zeilen {start_row_index_in_sheet} bis {end_row_index_in_sheet}...") + # Lade aktuelle Daten (optional, aber sicher) + if not sheet_handler.load_data(): + debug_print("FEHLER beim Laden der Daten in process_website_batch.") + return all_data = sheet_handler.get_all_data_with_headers() if not all_data or len(all_data) <= 5: debug_print("FEHLER/WARNUNG: Keine Daten zum Verarbeiten in process_website_batch gefunden.") return sheet = sheet_handler.sheet + + # Hole Indizes timestamp_col_key = "Website Scrape Timestamp" timestamp_col_index = COLUMN_MAP.get(timestamp_col_key) website_col_index = COLUMN_MAP.get("CRM Website") @@ -2225,7 +2214,7 @@ def process_website_batch(sheet_handler, start_row_index_in_sheet, end_row_index version_col_index = COLUMN_MAP.get("Version") if None in [timestamp_col_index, website_col_index, rohtext_col_index, summary_col_index, version_col_index]: - debug_print(f"FEHLER: Mindestens ein benötigter Spaltenindex für process_website_batch fehlt in COLUMN_MAP (benötigt: '{timestamp_col_key}', 'CRM Website', 'Website Rohtext', 'Website Zusammenfassung', 'Version').") + debug_print("FEHLER: Mindestens ein benötigter Spaltenindex für process_website_batch fehlt in COLUMN_MAP.") return ts_col_letter = sheet_handler._get_col_letter(timestamp_col_index + 1) @@ -2234,7 +2223,7 @@ def process_website_batch(sheet_handler, start_row_index_in_sheet, end_row_index version_col_letter = sheet_handler._get_col_letter(version_col_index + 1) processed_count = 0 - skipped_count = 0 + skipped_url_count = 0 # Zähle nur Zeilen ohne URL for i in range(start_row_index_in_sheet, end_row_index_in_sheet + 1): row_index_in_list = i - 1 @@ -2244,31 +2233,15 @@ def process_website_batch(sheet_handler, start_row_index_in_sheet, end_row_index row = all_data[row_index_in_list] - # --- ERZWUNGENE DEBUGGING Timestamp-Prüfung AT --- - ts_value_at = "INDEX_FEHLER" - ts_at_is_set = False - if len(row) > timestamp_col_index: - ts_value_at = row[timestamp_col_index] - # Konvertiere zu String VOR strip, um Fehler bei None etc. zu vermeiden - ts_at_is_set = bool(str(ts_value_at).strip()) - # Gib für JEDE Zeile im Bereich die Prüfung aus - debug_print(f"Zeile {i} (Website Check): Prüfe Timestamp {ts_col_letter} (Index {timestamp_col_index}). Rohwert='{ts_value_at}', Strip='{str(ts_value_at).strip()}', Überspringen? -> {ts_at_is_set}") - # --- Ende ERZWUNGENE DEBUGGING --- + # --- KEINE Timestamp-Prüfung mehr hier --- - if ts_at_is_set: - skipped_count += 1 - # Logge nur noch selten, da wir die Prüfung oben schon loggen - # if skipped_count == 1 or skipped_count % 100 == 0: - # debug_print(f"Zeile {i}: Überspringe Website-Scraping (Timestamp {ts_col_letter} vorhanden). ({skipped_count} gesamt übersprungen)") - continue - # --- Ende Timestamp-Prüfung --- - - # (Rest der Logik zum Scrapen und Updaten wie zuvor) website_url = row[website_col_index] if len(row) > website_col_index else "" if not website_url or website_url.strip().lower() == "k.a.": - skipped_count += 1 + # debug_print(f"Zeile {i}: Kein gültiger Website-Eintrag, überspringe Website-Scraping.") + skipped_url_count += 1 continue + # debug_print(f"Zeile {i}: Verarbeite Website {website_url}...") # Weniger Lärm raw_text = get_website_raw(website_url) summary = summarize_website_content(raw_text) processed_count += 1 @@ -2285,19 +2258,28 @@ def process_website_batch(sheet_handler, start_row_index_in_sheet, end_row_index if updates: success = sheet_handler.batch_update_cells(updates) if success: - debug_print(f"Zeile {i}: Website-Daten erfolgreich aktualisiert.") # Geänderte Log-Nachricht - if not success: - debug_print(f"FEHLER beim Schreiben der Website-Updates für Zeile {i}.") + # debug_print(f"Zeile {i}: Website-Daten erfolgreich aktualisiert.") # Weniger Lärm + pass + else: + debug_print(f"FEHLER beim Schreiben der Website-Updates für Zeile {i}.") time.sleep(Config.RETRY_DELAY) - debug_print(f"Website-Scraping (Batch) abgeschlossen. {processed_count} Websites gescraped, {skipped_count} Zeilen übersprungen.") + debug_print(f"Website-Scraping (Batch) abgeschlossen. {processed_count} Websites gescraped, {skipped_url_count} Zeilen ohne URL übersprungen.") # Komplette Funktion process_branch_batch (prüft jetzt Timestamp AO mit erzwungenem Debugging) +# Komplette Funktion process_branch_batch (OHNE interne Timestamp-Prüfung) def process_branch_batch(sheet_handler, start_row_index_in_sheet, end_row_index_in_sheet): - """Batch-Prozess für Brancheneinschätzung.""" + """ + Batch-Prozess für Brancheneinschätzung. Verarbeitet ALLE Zeilen im + angegebenen Bereich und setzt AO + AP Timestamps. + """ debug_print(f"Starte Brancheneinschätzung (Batch) für Zeilen {start_row_index_in_sheet} bis {end_row_index_in_sheet}...") + # Lade aktuelle Daten + if not sheet_handler.load_data(): + debug_print("FEHLER beim Laden der Daten in process_branch_batch.") + return all_data = sheet_handler.get_all_data_with_headers() if not all_data or len(all_data) <= 5: debug_print("FEHLER/WARNUNG: Keine Daten zum Verarbeiten in process_branch_batch gefunden.") @@ -2305,7 +2287,7 @@ def process_branch_batch(sheet_handler, start_row_index_in_sheet, end_row_index_ sheet = sheet_handler.sheet - # Hole Indizes aus COLUMN_MAP + # Hole Indizes timestamp_col_key = "Timestamp letzte Prüfung" timestamp_col_index = COLUMN_MAP.get(timestamp_col_key) branche_crm_idx = COLUMN_MAP.get("CRM Branche") @@ -2332,7 +2314,7 @@ def process_branch_batch(sheet_handler, start_row_index_in_sheet, end_row_index_ branch_y_letter = sheet_handler._get_col_letter(branch_y_idx + 1) processed_count = 0 - skipped_count = 0 + # skipped_count nicht mehr benötigt if not ALLOWED_TARGET_BRANCHES: load_target_schema() @@ -2348,30 +2330,16 @@ def process_branch_batch(sheet_handler, start_row_index_in_sheet, end_row_index_ row = all_data[row_index_in_list] - # --- ERZWUNGENE DEBUGGING Timestamp-Prüfung AO --- - ts_value_ao = "INDEX_FEHLER" - ts_ao_is_set = False - if len(row) > timestamp_col_index: - ts_value_ao = row[timestamp_col_index] - ts_ao_is_set = bool(str(ts_value_ao).strip()) - # Gib für JEDE Zeile im Bereich die Prüfung aus - debug_print(f"Zeile {i} (Branch Check): Prüfe Timestamp {ts_col_letter} (Index {timestamp_col_index}). Rohwert='{ts_value_ao}', Strip='{str(ts_value_ao).strip()}', Überspringen? -> {ts_ao_is_set}") - # --- Ende ERZWUNGENE DEBUGGING --- + # --- KEINE Timestamp-Prüfung mehr hier --- - if ts_ao_is_set: - skipped_count += 1 - # if skipped_count == 1 or skipped_count % 100 == 0: - # debug_print(f"Zeile {i}: Überspringe Branchen-Einschätzung (Timestamp {ts_col_letter} vorhanden). ({skipped_count} gesamt übersprungen)") - continue - # --- Ende Timestamp-Prüfung --- - - # (Restliche Logik zum Datenholen und Bewerten wie zuvor) + # Daten holen crm_branche = row[branche_crm_idx] if len(row) > branche_crm_idx else "" beschreibung = row[beschreibung_idx] if len(row) > beschreibung_idx else "" wiki_branche = row[branche_wiki_idx] if len(row) > branche_wiki_idx else "" wiki_kategorien = row[kategorien_wiki_idx] if len(row) > kategorien_wiki_idx else "" website_summary = row[summary_web_idx] if len(row) > summary_web_idx else "" + # debug_print(f"Zeile {i}: Starte Brancheneinschätzung...") # Weniger Lärm result = evaluate_branche_chatgpt(crm_branche, beschreibung, wiki_branche, wiki_kategorien, website_summary) processed_count += 1 @@ -2388,13 +2356,14 @@ def process_branch_batch(sheet_handler, start_row_index_in_sheet, end_row_index_ if updates: success = sheet_handler.batch_update_cells(updates) if success: - debug_print(f"Zeile {i}: Branch-Einschätzung erfolgreich aktualisiert.") # Geänderte Log-Nachricht - if not success: + # debug_print(f"Zeile {i}: Branch-Einschätzung erfolgreich aktualisiert.") # Weniger Lärm + pass + else: debug_print(f"FEHLER beim Schreiben der Branch-Updates für Zeile {i}.") time.sleep(Config.RETRY_DELAY) - debug_print(f"Brancheneinschätzung (Batch) abgeschlossen. {processed_count} Zeilen eingeschätzt, {skipped_count} Zeilen übersprungen.") + debug_print(f"Brancheneinschätzung (Batch) abgeschlossen. {processed_count} Zeilen eingeschätzt.") def process_website_batch(sheet_handler, start_row_index_in_sheet, end_row_index_in_sheet): """Batch-Prozess für Website-Scraping (Rohtext & Zusammenfassung).""" @@ -2504,55 +2473,44 @@ def process_branch_batch(sheet_handler, start_row_index_in_sheet, end_row_index_ # - sheet_handler ist eine initialisierte Instanz von GoogleSheetHandler (mit der korrekten get_start_row_index Methode). # - Globale Konstante header_rows (oder besser, hol sie vom sheet_handler?) +# Komplette run_dispatcher Funktion (Start immer basierend auf AO) def run_dispatcher(mode, sheet_handler, row_limit=None): """ Wählt den passenden Batch-Prozess basierend auf dem Modus. - Ermittelt die Startzeile dynamisch basierend auf dem Timestamp in der relevanten Spalte. - Die aufgerufenen Prozessfunktionen laden ihre Daten selbst oder verwenden den Handler. + Ermittelt die Startzeile IMMER basierend auf dem Timestamp letzte Prüfung (AO). + Die aufgerufenen Prozessfunktionen verarbeiten den vorgegebenen Bereich. """ debug_print(f"Starte Dispatcher im Modus '{mode}' mit row_limit={row_limit}.") - header_rows = 5 # Feste Annahme für Header + header_rows = 5 - # --- Startzeilen-Ermittlung basierend auf Modus --- - start_col_key = "Timestamp letzte Prüfung" # Standard (Spalte AO) + # --- Startzeilen-Ermittlung IMMER basierend auf AO --- + start_col_key = "Timestamp letzte Prüfung" # Spalte AO min_start_row = 7 - if mode == "website": start_col_key = "Website Scrape Timestamp" # AT - elif mode == "wiki": start_col_key = "Wikipedia Timestamp" # AN - elif mode == "branch": start_col_key = "Timestamp letzte Prüfung" # AO - elif mode == "combined": start_col_key = "Timestamp letzte Prüfung" # AO (Combined startet, wo der letzte Schritt fehlt) debug_print(f"Dispatcher: Ermittle Startzeile basierend auf Spalte '{start_col_key}'...") - # get_start_row_index wird aufgerufen, lädt die Daten neu start_data_index = sheet_handler.get_start_row_index(check_column_key=start_col_key, min_sheet_row=min_start_row) - # Fehlerprüfung für get_start_row_index if start_data_index == -1: debug_print(f"FEHLER: Konnte Startzeile nicht ermitteln (Spaltenschlüssel '{start_col_key}' in COLUMN_MAP prüfen?). Dispatcher beendet.") return - # Umrechnung des 0-basierten Daten-Index in die 1-basierte Sheet-Zeilennummer start_row_index_in_sheet = start_data_index + header_rows + 1 + total_sheet_rows = len(sheet_handler.sheet_values) # Greife auf Daten im Handler zu - # Hole Gesamtzahl der Zeilen (nach potentiellem Neuladen in get_start_row_index) - total_sheet_rows = len(sheet_handler.sheet_values) - - # Prüfe, ob der Startpunkt überhaupt im Sheet liegt oder ob das Sheet leer ist - if start_data_index >= len(sheet_handler.get_data()): # Prüfe gegen Daten ohne Header - debug_print(f"Ermittelter Start-Daten-Index ({start_data_index}) liegt nach der letzten Datenzeile ({len(sheet_handler.get_data())-1}). Keine neuen Zeilen zu verarbeiten. Dispatcher beendet.") + if start_data_index >= len(sheet_handler.get_data()): + debug_print(f"Ermittelter Start-Daten-Index ({start_data_index}) liegt nach der letzten Datenzeile. Keine neuen Zeilen zu verarbeiten. Dispatcher beendet.") return elif start_row_index_in_sheet > total_sheet_rows: - # Dieser Fall sollte durch die Prüfung oben abgedeckt sein, aber zur Sicherheit debug_print(f"Sheet hat keine Datenzeilen oder Startzeile ({start_row_index_in_sheet}) ist ungültig. Dispatcher beendet.") return - # --- Endzeilen-Ermittlung --- + # --- Endzeilen-Ermittlung (wie gehabt) --- if row_limit is not None and row_limit > 0: - # Berechne Endzeile basierend auf Startzeile und Limit end_row_index_in_sheet = min(start_row_index_in_sheet + row_limit - 1, total_sheet_rows) elif row_limit == 0: debug_print("Zeilenlimit ist 0. Keine Verarbeitung.") return - else: # Kein Limit oder negatives Limit -> bis zum Ende des Sheets + else: end_row_index_in_sheet = total_sheet_rows debug_print(f"Dispatcher: Verarbeitung geplant für Sheet-Zeilen {start_row_index_in_sheet} bis {end_row_index_in_sheet}.") @@ -2562,22 +2520,27 @@ def run_dispatcher(mode, sheet_handler, row_limit=None): return # --- Modusauswahl und Aufruf der Verarbeitungsfunktionen --- + # Die Prozessfunktionen erhalten den Bereich und führen ihre Aufgabe aus, + # setzen aber nur noch ihren *eigenen* Timestamp (falls relevant) oder AO/AP. + # Sie überspringen NICHT mehr basierend auf Timestamps innerhalb ihrer Schleife. try: if mode == "wiki": + # Führt Wiki-Verifizierung für den Bereich aus und setzt AN process_verification_only(sheet_handler, start_row_index_in_sheet, end_row_index_in_sheet) elif mode == "website": + # Führt Website-Scraping für den Bereich aus und setzt AT + AP process_website_batch(sheet_handler, start_row_index_in_sheet, end_row_index_in_sheet) elif mode == "branch": + # Führt Branch-Einschätzung für den Bereich aus und setzt AO + AP process_branch_batch(sheet_handler, start_row_index_in_sheet, end_row_index_in_sheet) elif mode == "combined": debug_print("--- Start Combined Mode: Wiki ---") - process_verification_only(sheet_handler, start_row_index_in_sheet, end_row_index_in_sheet) # Lädt Daten, prüft AN - time.sleep(1) # Kurze Pause + process_verification_only(sheet_handler, start_row_index_in_sheet, end_row_index_in_sheet) # Setzt AN + # Keine Pause nötig, da Datenaktualität nicht mehr das Hauptproblem war debug_print("--- Start Combined Mode: Website ---") - process_website_batch(sheet_handler, start_row_index_in_sheet, end_row_index_in_sheet) # Lädt Daten, prüft AT - time.sleep(1) # Kurze Pause + process_website_batch(sheet_handler, start_row_index_in_sheet, end_row_index_in_sheet) # Setzt AT + AP debug_print("--- Start Combined Mode: Branch ---") - process_branch_batch(sheet_handler, start_row_index_in_sheet, end_row_index_in_sheet) # Lädt Daten, prüft AO + process_branch_batch(sheet_handler, start_row_index_in_sheet, end_row_index_in_sheet) # Setzt AO + AP (überschreibt AP) debug_print("--- Combined Mode abgeschlossen ---") else: debug_print(f"Ungültiger Modus '{mode}' wurde im Dispatcher übergeben.")