diff --git a/brancheneinstufung.py b/brancheneinstufung.py index 6f608d4f..f186de29 100644 --- a/brancheneinstufung.py +++ b/brancheneinstufung.py @@ -5018,84 +5018,202 @@ class DataProcessor: f"{skipped_m_filled_count} M gefüllt." ) - # process_wiki_updates_from_chatgpt Methode - def process_wiki_updates_from_chatgpt(self, row_limit=None): # <<< Methode in DataProcessor + def process_wiki_updates_from_chatgpt(self, row_limit=None): """ Identifiziert Zeilen (S nicht OK/Updated/Copied/Invalid), prüft ob U eine *valide* und *andere* Wiki-URL ist. - Wenn ja: Kopiert U->M, markiert S='X (URL Copied)', U='URL übernommen', löscht TS/Version, setzt ReEval-Flag A. - Wenn nein (U keine URL, U==M, oder U ungültig): LÖSCHT den Inhalt von U und markiert S als 'X (Invalid Suggestion)'. Verarbeitet maximal row_limit Zeilen. """ - logging.info(f"Starte Modus: Wiki-Updates (URL-Validierung & Löschen ungültiger Vorschläge). Limit: {limit if limit is not None else 'Unbegrenzt'}") - if not self.sheet_handler.load_data(): return logging.error("FEHLER beim Laden der Daten.") - all_data = self.sheet_handler.get_all_data_with_headers(); header_rows = 5 - if not all_data or len(all_data) <= header_rows: logging.warning("Keine Daten gefunden."); return + logging.info( + f"Starte Modus: Wiki-Updates (URL-Validierung & Löschen ungültiger Vorschläge). " + f"Limit: {row_limit if row_limit is not None else 'Unbegrenzt'}" + ) + if not self.sheet_handler.load_data(): + return logging.error("FEHLER beim Laden der Daten.") + + all_data = self.sheet_handler.get_all_data_with_headers() + header_rows = 5 + if not all_data or len(all_data) <= header_rows: + logging.warning("Keine Daten gefunden oder nur Header.") + return + data_rows = all_data[header_rows:] - required_keys = [ "Chat Wiki Konsistenzprüfung", "Chat Vorschlag Wiki Artikel", "Wiki URL", "Wikipedia Timestamp", "Wiki Verif. Timestamp", "Timestamp letzte Prüfung", "Version", "ReEval Flag", "Wiki Absatz", "Wiki Branche", "Wiki Umsatz", "Wiki Mitarbeiter", "Wiki Kategorien", "Begründung bei Abweichung" ]; - col_indices = {}; all_keys_found = True; for key in required_keys: idx = COLUMN_MAP.get(key); col_indices[key] = idx; if idx is None: logging.critical(f"FEHLER: Schlüssel '{key}' fehlt! Modus abgebrochen."); all_keys_found = False; - if not all_keys_found: return; - all_sheet_updates = []; processed_rows_count = 0; updated_url_count = 0; cleared_suggestion_count = 0; + # Spalten-Indizes prüfen + required_keys = [ + "Chat Wiki Konsistenzprüfung", "Chat Vorschlag Wiki Artikel", "Wiki URL", + "Wikipedia Timestamp", "Wiki Verif. Timestamp", "Timestamp letzte Prüfung", + "Version", "ReEval Flag", "Wiki Absatz", "Wiki Branche", "Wiki Umsatz", + "Wiki Mitarbeiter", "Wiki Kategorien", "Begründung bei Abweichung" + ] + col_indices = {} + all_keys_found = True + for key in required_keys: + idx = COLUMN_MAP.get(key) + col_indices[key] = idx + if idx is None: + logging.critical(f"FEHLER: Schlüssel '{key}' fehlt! Modus abgebrochen.") + all_keys_found = False + if not all_keys_found: + return + + all_sheet_updates = [] + processed_rows_count = 0 + updated_url_count = 0 + cleared_suggestion_count = 0 + + # Durch die Zeilen iterieren for idx, row in enumerate(data_rows): - row_num_in_sheet = idx + header_rows + 1; - if limit is not None and processed_rows_count >= limit: logging.info(f"Limit ({limit}) erreicht."); break; - max_needed_idx = max(col_indices.values()); if len(row) <= max_needed_idx: logging.debug(f"Zeile {row_num_in_sheet}: Übersprungen (Zeile zu kurz)."); continue; + row_num_in_sheet = idx + header_rows + 1 - konsistenz_s = self._get_cell_value(row, "Chat Wiki Konsistenzprüfung").strip(); - vorschlag_u = self._get_cell_value(row, "Chat Vorschlag Wiki Artikel").strip(); - url_m = self._get_cell_value(row, "Wiki URL").strip(); + # Limit prüfen + if row_limit is not None and processed_rows_count >= row_limit: + logging.info(f"Limit ({row_limit}) erreicht.") + break - konsistenz_s_upper = konsistenz_s.upper(); - is_candidate_for_check = bool(konsistenz_s_upper) and konsistenz_s_upper not in ["OK", "X (UPDATED)", "X (URL COPIED)", "X (INVALID SUGGESTION)", "?"]; + # Zeile überspringen, wenn zu kurz + max_needed_idx = max(col_indices.values()) + if len(row) <= max_needed_idx: + logging.debug( + f"Zeile {row_num_in_sheet}: Übersprungen (Zeile zu kurz)." + ) + continue + + # Zellenwerte holen + konsistenz_s = self._get_cell_value(row, "Chat Wiki Konsistenzprüfung").strip() + vorschlag_u = self._get_cell_value(row, "Chat Vorschlag Wiki Artikel").strip() + url_m = self._get_cell_value(row, "Wiki URL").strip() + + # Kandidatenstatus prüfen + konsistenz_s_upper = konsistenz_s.upper() + is_candidate_for_check = ( + bool(konsistenz_s_upper) + and konsistenz_s_upper not in [ + "OK", "X (UPDATED)", "X (URL COPIED)", "X (INVALID SUGGESTION)", "?" + ] + ) if is_candidate_for_check or (konsistenz_s_upper == "?" and not vorschlag_u): - logging.debug(f"Zeile {row_num_in_sheet}: Kandidat für Wiki-Update-Prüfung (Status S = '{konsistenz_s}'). Vorschlag U = '{vorschlag_u}'"); - processed_rows_count += 1; is_update_candidate = False; new_url = ""; - condition2_u_is_wiki_url = vorschlag_u.lower().startswith(("http://", "https://")) and "wikipedia.org/wiki/" in vorschlag_u.lower(); - if condition2_u_is_wiki_url: - new_url = vorschlag_u; - condition3_u_differs_m = simple_normalize_url(new_url) != simple_normalize_url(url_m); # Global Function - if condition3_u_differs_m: - logging.debug(f" -> Prüfe Validität der neuen URL: {new_url}..."); - try: condition4_u_is_valid = is_valid_wikipedia_article_url(new_url); # Global Function with Retry - except Exception as e_valid: logging.error(f" -> Fehler bei Validierung der URL '{new_url}': {e_valid}. Behandle als ungültig."); condition4_u_is_valid = False; - if condition4_u_is_valid: is_update_candidate = True; logging.debug(f" -> URL '{new_url}' ist ein valider Artikel."); - else: logging.debug(f" -> URL '{new_url}' ist KEIN valider Artikel laut API Check."); - else: logging.debug(f" -> Vorschlag U ist identisch mit URL M."); - else: logging.debug(f" -> Vorschlag U ist keine Wikipedia URL ('{vorschlag_u}')."); + logging.debug( + f"Zeile {row_num_in_sheet}: Kandidat für Wiki-Update-Prüfung " + f"(Status S = '{konsistenz_s}'). Vorschlag U = '{vorschlag_u}'" + ) + processed_rows_count += 1 - if is_update_candidate: - logging.info(f"Zeile {row_num_in_sheet}: Update-Kandidat VALIDIERUNG ERFOLGREICH. Setze ReEval-Flag 'x' und bereite Updates vor für URL: {new_url}"); - updated_url_count += 1; - m_l=self.sheet_handler._get_col_letter(col_indices["Wiki URL"]+1); s_l=self.sheet_handler._get_col_letter(col_indices["Chat Wiki Konsistenzprüfung"]+1); u_l=self.sheet_handler._get_col_letter(col_indices["Chat Vorschlag Wiki Artikel"]+1); - a_l=self.sheet_handler._get_col_letter(col_indices["ReEval Flag"]+1); - n_idx = col_indices["Wiki Absatz"]; v_idx = col_indices["Begründung bei Abweichung"]; n_l=self.sheet_handler._get_col_letter(n_idx+1); v_l=self.sheet_handler._get_col_letter(v_idx+1); - an_l=self.sheet_handler._get_col_letter(col_indices["Wikipedia Timestamp"]+1); ax_l=self.sheet_handler._get_col_letter(col_indices["Wiki Verif. Timestamp"]+1); ao_l=self.sheet_handler._get_col_letter(col_indices["Timestamp letzte Prüfung"]+1); ap_l=self.sheet_handler._get_col_letter(col_indices["Version"]+1); + # Update-Kandidat validieren + is_update_candidate = False + new_url = "" + condition2 = ( + vorschlag_u.lower().startswith(("http://", "https://")) + and "wikipedia.org/wiki/" in vorschlag_u.lower() + ) - all_sheet_updates.extend([ - {'range': f'{m_l}{row_num_in_sheet}', 'values': [[new_url]]}, {'range': f'{s_l}{row_num_in_sheet}', 'values': [["X (URL Copied)"]]}, {'range': f'{u_l}{row_num_in_sheet}', 'values': [["URL übernommen"]]}, - {'range': f'{n_l}{row_num_in_sheet}:{v_l}{row_num_in_sheet}', 'values': [[''] * (v_idx - n_idx + 1)]}, - {'range': f'{an_l}{row_num_in_sheet}', 'values': [['']]}, {'range': f'{ax_l}{row_num_in_sheet}', 'values': [['']]}, - {'range': f'{ao_l}{row_num_in_sheet}', 'values': [['']]}, {'range': f'{ap_l}{row_num_in_sheet}', 'values': [['']]}, - {'range': f'{a_l}{row_num_in_sheet}', 'values': [["x"]]}, - ]); - else: # <<< Continue from here - logging.info(f"Zeile {row_num_in_sheet}: Vorschlag U ('{vorschlag_u}') ist ungültig/identisch. Lösche U und setze Status S."); - cleared_suggestion_count += 1; - s_l=self.sheet_handler._get_col_letter(col_indices["Chat Wiki Konsistenzprüfung"]+1); u_l=self.sheet_handler._get_col_letter(col_indices["Chat Vorschlag Wiki Artikel"]+1); - all_sheet_updates.extend([ - {'range': f'{s_l}{row_num_in_sheet}', 'values': [["X (Invalid Suggestion)"]]}, - {'range': f'{u_l}{row_num_in_sheet}', 'values': [[""]]} - ]); + if condition2: + new_url = vorschlag_u + condition3 = ( + simple_normalize_url(new_url) + != simple_normalize_url(url_m) + ) + if condition3: + logging.debug(f" -> Prüfe Validität der neuen URL: {new_url}...") + try: + condition4 = is_valid_wikipedia_article_url(new_url) + except Exception as e_valid: + logging.error( + f" -> Fehler bei Validierung der URL '{new_url}': {e_valid}. " + "Behandle als ungültig." + ) + condition4 = False + if condition4: + is_update_candidate = True + logging.debug(f" -> URL '{new_url}' ist ein valider Artikel.") + else: + logging.debug( + f" -> URL '{new_url}' ist KEIN valider Artikel laut API Check." + ) + else: + logging.debug(f" -> Vorschlag U ist identisch mit URL M.") + else: + logging.debug( + f" -> Vorschlag U ist keine Wikipedia URL ('{vorschlag_u}')." + ) + + # Update oder Cleanup vorbereiten + if is_update_candidate: + logging.info( + f"Zeile {row_num_in_sheet}: Update-Kandidat VALIDIERUNG ERFOLGREICH. " + f"Setze ReEval-Flag 'x' und bereite Updates vor für URL: {new_url}" + ) + updated_url_count += 1 + + # Spaltenbuchstaben ermitteln + m_l = self.sheet_handler._get_col_letter(col_indices["Wiki URL"] + 1) + s_l = self.sheet_handler._get_col_letter(col_indices["Chat Wiki Konsistenzprüfung"] + 1) + u_l = self.sheet_handler._get_col_letter(col_indices["Chat Vorschlag Wiki Artikel"] + 1) + a_l = self.sheet_handler._get_col_letter(col_indices["ReEval Flag"] + 1) + + n_idx = col_indices["Wiki Absatz"] + v_idx = col_indices["Begründung bei Abweichung"] + n_l = self.sheet_handler._get_col_letter(n_idx + 1) + v_l = self.sheet_handler._get_col_letter(v_idx + 1) + + an_l = self.sheet_handler._get_col_letter(col_indices["Wikipedia Timestamp"] + 1) + ax_l = self.sheet_handler._get_col_letter(col_indices["Wiki Verif. Timestamp"]+ 1) + ao_l = self.sheet_handler._get_col_letter(col_indices["Timestamp letzte Prüfung"]+1) + ap_l = self.sheet_handler._get_col_letter(col_indices["Version"] + 1) + + all_sheet_updates.extend([ + {'range': f'{m_l}{row_num_in_sheet}', 'values': [[ new_url ]]}, + {'range': f'{s_l}{row_num_in_sheet}', 'values': [[ "X (URL Copied)" ]]}, + {'range': f'{u_l}{row_num_in_sheet}', 'values': [[ "URL übernommen" ]]}, + { + 'range': f'{n_l}{row_num_in_sheet}:{v_l}{row_num_in_sheet}', + 'values': [[''] * (v_idx - n_idx + 1)] + }, + {'range': f'{an_l}{row_num_in_sheet}', 'values': [['']]}, + {'range': f'{ax_l}{row_num_in_sheet}', 'values': [['']]}, + {'range': f'{ao_l}{row_num_in_sheet}', 'values': [['']]}, + {'range': f'{ap_l}{row_num_in_sheet}', 'values': [['']]}, + {'range': f'{a_l}{row_num_in_sheet}', 'values': [[ "x" ]]}, + ]) + else: + logging.info( + f"Zeile {row_num_in_sheet}: Vorschlag U ('{vorschlag_u}') " + "ist ungültig/identisch. Lösche U und setze Status S." + ) + cleared_suggestion_count += 1 + + s_l = self.sheet_handler._get_col_letter(col_indices["Chat Wiki Konsistenzprüfung"] + 1) + u_l = self.sheet_handler._get_col_letter(col_indices["Chat Vorschlag Wiki Artikel"] + 1) + + all_sheet_updates.extend([ + {'range': f'{s_l}{row_num_in_sheet}', 'values': [[ "X (Invalid Suggestion)" ]]}, + {'range': f'{u_l}{row_num_in_sheet}', 'values': [[ "" ]]}, + ]) + + # Nach der Schleife: Batch-Update senden if all_sheet_updates: - logging.info(f"Sende Batch-Update für {processed_rows_count} geprüfte Zeilen ({len(all_sheet_updates)} Zellen)..."); - success = self.sheet_handler.batch_update_cells(all_sheet_updates); - if success: logging.info(f"Sheet-Update für Wiki-Updates erfolgreich."); - else: logging.error("FEHLER beim Sheet-Update für Wiki-Updates."); - else: logging.info("Keine Zeilen gefunden, die Wiki-Updates benötigen."); - - logging.info(f"Wiki-Updates abgeschlossen. {processed_rows_count} Zeilen geprüft. {updated_url_count} URLs kopiert & für ReEval markiert, {cleared_suggestion_count} ungültige Vorschläge gelöscht/markiert."); + logging.info( + f"Sende Batch-Update für {processed_rows_count} geprüfte Zeilen " + f"({len(all_sheet_updates)} Zellen)..." + ) + success = self.sheet_handler.batch_update_cells(all_sheet_updates) + if success: + logging.info("Sheet-Update für Wiki-Updates erfolgreich.") + else: + logging.error("FEHLER beim Sheet-Update für Wiki-Updates.") + else: + logging.info( + "Keine Zeilen gefunden, die eine Wiki-URL-Korrektur oder " + "Vorschlagsbereinigung benötigen." + ) + logging.info( + f"Wiki-Updates abgeschlossen. {processed_rows_count} Zeilen geprüft. " + f"{updated_url_count} URLs kopiert & für ReEval markiert, " + f"{cleared_suggestion_count} ungültige Vorschläge gelöscht/markiert." + ) # process_website_details Methode (früher process_website_details_for_marked_rows) def process_website_details(self, limit=None): # <<< Methode in DataProcessor