This commit is contained in:
2025-04-18 06:10:21 +00:00
parent a45e1a3109
commit 5ca84818e9

View File

@@ -3210,54 +3210,46 @@ class DataProcessor:
def _process_single_row(self, row_num_in_sheet, row_data, process_wiki=True, process_chatgpt=True, process_website=True): def _process_single_row(self, row_num_in_sheet, row_data, process_wiki=True, process_chatgpt=True, process_website=True):
""" """
Verarbeitet die Daten für eine einzelne Zeile, prüft Timestamps für jeden Teilbereich Verarbeitet die Daten für eine einzelne Zeile, prüft Timestamps für jeden Teilbereich
und priorisiert die URL in Spalte M, wenn Wiki neu verarbeitet wird. und stellt sicher, dass aktuelle Wiki-Daten für Branch-Eval verwendet werden.
""" """
debug_print(f"--- Starte Verarbeitung für Zeile {row_num_in_sheet} ---") debug_print(f"--- Starte Verarbeitung für Zeile {row_num_in_sheet} ---")
updates = [] updates = []
now_timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") now_timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
any_processing_done = False any_processing_done = False
# Hilfsfunktion für sicheren Zugriff # Hilfsfunktion
def get_cell_value(key): def get_cell_value(key):
idx = COLUMN_MAP.get(key) idx = COLUMN_MAP.get(key)
if idx is not None and len(row_data) > idx: return row_data[idx] if idx is not None and len(row_data) > idx: return row_data[idx]
return "" return ""
# Lese initiale Werte
company_name = get_cell_value("CRM Name") company_name = get_cell_value("CRM Name")
website_url = get_cell_value("CRM Website") website_url = get_cell_value("CRM Website"); original_website = website_url
original_website = website_url crm_branche = get_cell_value("CRM Branche"); crm_beschreibung = get_cell_value("CRM Beschreibung")
crm_branche = get_cell_value("CRM Branche") crm_wiki_url = get_cell_value("CRM Vorschlag Wiki URL")
crm_beschreibung = get_cell_value("CRM Beschreibung") konsistenz_s = get_cell_value("Chat Wiki Konsistenzprüfung")
crm_wiki_url = get_cell_value("CRM Vorschlag Wiki URL") # Wird nur noch als Fallback genutzt
konsistenz_s = get_cell_value("Chat Wiki Konsistenzprüfung") # Für Re-Parse Trigger
# Lese aktuelle Werte, die potenziell überschrieben werden
website_raw = get_cell_value("Website Rohtext") or "k.A." website_raw = get_cell_value("Website Rohtext") or "k.A."
website_summary = get_cell_value("Website Zusammenfassung") or "k.A." website_summary = get_cell_value("Website Zusammenfassung") or "k.A."
wiki_data = { # Lade aktuelle Wiki-Daten für den Fall, dass Wiki nicht neu geparst wird # Initialisiere wiki_data mit Werten aus dem Sheet (Fallback)
'url': get_cell_value("Wiki URL") or 'k.A.', wiki_data = {
'first_paragraph': get_cell_value("Wiki Absatz") or 'k.A.', 'url': get_cell_value("Wiki URL") or 'k.A.', 'first_paragraph': get_cell_value("Wiki Absatz") or 'k.A.',
'branche': get_cell_value("Wiki Branche") or 'k.A.', 'branche': get_cell_value("Wiki Branche") or 'k.A.', 'umsatz': get_cell_value("Wiki Umsatz") or 'k.A.',
'umsatz': get_cell_value("Wiki Umsatz") or 'k.A.', 'mitarbeiter': get_cell_value("Wiki Mitarbeiter") or 'k.A.', 'categories': get_cell_value("Wiki Kategorien") or 'k.A.'
'mitarbeiter': get_cell_value("Wiki Mitarbeiter") or 'k.A.',
'categories': get_cell_value("Wiki Kategorien") or 'k.A.'
} }
wiki_data_updated_in_this_run = False # Flag, ob Wiki neu geparst wurde
# --- 1. Website Handling (wie zuletzt -> prüft AT) --- # --- 1. Website Handling (prüft AT) ---
website_ts_needed = process_website and not get_cell_value("Website Scrape Timestamp").strip() website_ts_needed = process_website and not get_cell_value("Website Scrape Timestamp").strip()
if website_ts_needed: if website_ts_needed:
debug_print(f"Zeile {row_num_in_sheet}: Starte Website Verarbeitung (Timestamp AT fehlt)...") any_processing_done = True; debug_print(f"Zeile {row_num_in_sheet}: Starte Website Verarbeitung...")
any_processing_done = True # --- Lookup & Scraping ---
# --- Lookup ---
if not website_url or website_url.strip().lower() == "k.a.": if not website_url or website_url.strip().lower() == "k.a.":
new_website = serp_website_lookup(company_name) new_website = serp_website_lookup(company_name)
if new_website != "k.A.": website_url = new_website; debug_print(f"Zeile {row_num_in_sheet}: SERP Lookup: {website_url}"); if new_website != "k.A.": website_url = new_website;
if website_url != original_website: updates.append({'range': f'D{row_num_in_sheet}', 'values': [[website_url]]}) if website_url != original_website: updates.append({'range': f'D{row_num_in_sheet}', 'values': [[website_url]]})
else: debug_print(f"Zeile {row_num_in_sheet}: SERP Lookup erfolglos.")
# --- Scraping ---
if website_url and website_url.strip().lower() != "k.a.": if website_url and website_url.strip().lower() != "k.a.":
new_website_raw = get_website_raw(website_url) new_website_raw = get_website_raw(website_url); new_website_summary = summarize_website_content(new_website_raw)
new_website_summary = summarize_website_content(new_website_raw)
if new_website_raw != website_raw: updates.append({'range': f'AR{row_num_in_sheet}', 'values': [[new_website_raw]]}); website_raw = new_website_raw if new_website_raw != website_raw: updates.append({'range': f'AR{row_num_in_sheet}', 'values': [[new_website_raw]]}); website_raw = new_website_raw
if new_website_summary != website_summary: updates.append({'range': f'AS{row_num_in_sheet}', 'values': [[new_website_summary]]}); website_summary = new_website_summary if new_website_summary != website_summary: updates.append({'range': f'AS{row_num_in_sheet}', 'values': [[new_website_summary]]}); website_summary = new_website_summary
else: else:
@@ -3265,103 +3257,94 @@ class DataProcessor:
if website_summary != "k.A.": updates.append({'range': f'AS{row_num_in_sheet}', 'values': [['k.A.']]}) if website_summary != "k.A.": updates.append({'range': f'AS{row_num_in_sheet}', 'values': [['k.A.']]})
website_raw, website_summary = "k.A.", "k.A." website_raw, website_summary = "k.A.", "k.A."
updates.append({'range': f'AT{row_num_in_sheet}', 'values': [[now_timestamp]]}) updates.append({'range': f'AT{row_num_in_sheet}', 'values': [[now_timestamp]]})
elif process_website: elif process_website: debug_print(f"Zeile {row_num_in_sheet}: Überspringe Website (AT vorhanden).")
debug_print(f"Zeile {row_num_in_sheet}: Überspringe Website Verarbeitung (Timestamp AT vorhanden).")
# --- 2. Wikipedia Handling (ANGEPASSTE LOGIK) --- # --- 2. Wikipedia Handling (prüft AN oder S='X (URL Copied)') ---
# Trigger für Reparsing: AN fehlt ODER Status S ist "X (URL Copied)"
wiki_ts_an_missing = not get_cell_value("Wikipedia Timestamp").strip() wiki_ts_an_missing = not get_cell_value("Wikipedia Timestamp").strip()
status_s_indicates_reparse = konsistenz_s.strip().upper() == "X (URL COPIED)" status_s_indicates_reparse = konsistenz_s.strip().upper() == "X (URL COPIED)"
reparse_wiki_needed = process_wiki and (wiki_ts_an_missing or status_s_indicates_reparse) reparse_wiki_needed = process_wiki and (wiki_ts_an_missing or status_s_indicates_reparse)
if reparse_wiki_needed: if reparse_wiki_needed:
debug_print(f"Zeile {row_num_in_sheet}: Starte Wikipedia Verarbeitung (Grund: AN fehlt? {wiki_ts_an_missing}, S='X (URL Copied)'? {status_s_indicates_reparse})...") any_processing_done = True; debug_print(f"Zeile {row_num_in_sheet}: Starte Wikipedia Verarbeitung (AN fehlt? {wiki_ts_an_missing}, S='X(Copied)'? {status_s_indicates_reparse})...")
any_processing_done = True new_wiki_data_extracted = None
new_wiki_data_extracted = None # Wird mit den neuen Daten gefüllt
# --- Priorisiere URL aus Spalte M --- # --- Priorisiere URL aus Spalte M ---
url_to_parse = get_cell_value("Wiki URL").strip() url_to_parse = get_cell_value("Wiki URL").strip() # Holt die URL, die ggf. von update_wiki kopiert wurde
if url_to_parse and url_to_parse.lower() not in ["k.a.", "kein artikel gefunden"] and url_to_parse.lower().startswith("http"): if url_to_parse and url_to_parse.lower() not in ["k.a.", "kein artikel gefunden"] and url_to_parse.lower().startswith("http"):
debug_print(f" -> Nutze vorhandene URL aus Spalte M: {url_to_parse}") debug_print(f" -> Nutze vorhandene URL aus Spalte M: {url_to_parse}")
new_wiki_data_extracted = self.wiki_scraper.extract_company_data(url_to_parse) new_wiki_data_extracted = self.wiki_scraper.extract_company_data(url_to_parse)
else: else:
# --- Nur wenn M leer/ungültig ist, starte die Suche --- # --- Nur wenn M leer/ungültig ist, starte die Suche ---
debug_print(f" -> Spalte M ('{url_to_parse}') ungültig/leer. Starte Wiki-Suche...") debug_print(f" -> Spalte M ('{url_to_parse}') ungültig/leer. Starte Wiki-Suche...")
# ... (Suchlogik wie zuvor, nutzt crm_wiki_url als Fallback) ...
valid_crm_wiki_url = crm_wiki_url if crm_wiki_url and crm_wiki_url.strip() not in ["", "k.A."] else None valid_crm_wiki_url = crm_wiki_url if crm_wiki_url and crm_wiki_url.strip() not in ["", "k.A."] else None
article_page = None article_page = None; current_website = website_url if website_url and website_url != 'k.A.' else original_website
current_website_for_validation = website_url if website_url and website_url != 'k.A.' else original_website # Nutze aktuelle URL if valid_crm_wiki_url: # ... (Prüfe CRM Vorschlag) ...
if valid_crm_wiki_url: else: article_page = self.wiki_scraper.search_company_article(company_name, current_website)
debug_print(f" -> Prüfe CRM Vorschlag L: {valid_crm_wiki_url}") if article_page: new_wiki_data_extracted = self.wiki_scraper.extract_company_data(article_page.url)
page = self.wiki_scraper._fetch_page_content(valid_crm_wiki_url.split('/')[-1]) else: new_wiki_data_extracted = {'url': 'Kein Artikel gefunden', 'first_paragraph': 'k.A.', 'branche': 'k.A.', 'umsatz': 'k.A.', 'mitarbeiter': 'k.A.', 'categories': 'k.A.'}
if page and self.wiki_scraper._validate_article(page, company_name, current_website_for_validation): article_page = page
else: debug_print(f" -> CRM Vorschlag L nicht validiert. Starte Suche..."); article_page = self.wiki_scraper.search_company_article(company_name, current_website_for_validation)
else:
debug_print(f" -> Kein CRM Vorschlag L. Starte Suche...")
article_page = self.wiki_scraper.search_company_article(company_name, current_website_for_validation)
if article_page: # --- WICHTIG: Überschreibe wiki_data mit den NEUEN Ergebnissen ---
debug_print(f" -> Artikel gefunden durch Suche: {article_page.url}")
new_wiki_data_extracted = self.wiki_scraper.extract_company_data(article_page.url)
else:
debug_print(f" -> Kein passender Wikipedia Artikel durch Suche gefunden.")
new_wiki_data_extracted = {'url': 'Kein Artikel gefunden', 'first_paragraph': 'k.A.', 'branche': 'k.A.', 'umsatz': 'k.A.', 'mitarbeiter': 'k.A.', 'categories': 'k.A.'}
# --- Updates für Wiki-Spalten vorbereiten ---
if new_wiki_data_extracted: if new_wiki_data_extracted:
wiki_data = new_wiki_data_extracted # Überschreibe alte Daten für nachfolgende Schritte wiki_data = new_wiki_data_extracted # <-- Hier werden die Daten für den Branch-Teil aktualisiert!
wiki_data_updated_in_this_run = True # Setze Flag
# Füge Updates für M-R und AN hinzu
updates.append({'range': f'M{row_num_in_sheet}', 'values': [[wiki_data.get('url', 'k.A.')]]}) updates.append({'range': f'M{row_num_in_sheet}', 'values': [[wiki_data.get('url', 'k.A.')]]})
updates.append({'range': f'N{row_num_in_sheet}', 'values': [[wiki_data.get('first_paragraph', 'k.A.')]]}) updates.append({'range': f'N{row_num_in_sheet}', 'values': [[wiki_data.get('first_paragraph', 'k.A.')]]})
# ... (Updates für O, P, Q, R) ...
updates.append({'range': f'O{row_num_in_sheet}', 'values': [[wiki_data.get('branche', 'k.A.')]]}) updates.append({'range': f'O{row_num_in_sheet}', 'values': [[wiki_data.get('branche', 'k.A.')]]})
updates.append({'range': f'P{row_num_in_sheet}', 'values': [[wiki_data.get('umsatz', 'k.A.')]]}) updates.append({'range': f'P{row_num_in_sheet}', 'values': [[wiki_data.get('umsatz', 'k.A.')]]})
updates.append({'range': f'Q{row_num_in_sheet}', 'values': [[wiki_data.get('mitarbeiter', 'k.A.')]]}) updates.append({'range': f'Q{row_num_in_sheet}', 'values': [[wiki_data.get('mitarbeiter', 'k.A.')]]})
updates.append({'range': f'R{row_num_in_sheet}', 'values': [[wiki_data.get('categories', 'k.A.')]]}) updates.append({'range': f'R{row_num_in_sheet}', 'values': [[wiki_data.get('categories', 'k.A.')]]})
updates.append({'range': f'AN{row_num_in_sheet}', 'values': [[now_timestamp]]}) # Setze AN Timestamp neu updates.append({'range': f'AN{row_num_in_sheet}', 'values': [[now_timestamp]]}) # Setze AN neu
# Wenn der Trigger "X (URL Copied)" war, setze S zurück # Wenn der Trigger "X (URL Copied)" war, setze S zurück
if status_s_indicates_reparse: if status_s_indicates_reparse:
konsistenz_s_idx = COLUMN_MAP.get("Chat Wiki Konsistenzprüfung") s_idx = COLUMN_MAP.get("Chat Wiki Konsistenzprüfung")
if konsistenz_s_idx is not None: if s_idx is not None:
s_col_letter = self.sheet_handler._get_col_letter(konsistenz_s_idx + 1) s_let = self.sheet_handler._get_col_letter(s_idx + 1)
updates.append({'range': f'{s_col_letter}{row_num_in_sheet}', 'values': [["?"]]}) # Setze auf "?" für erneute Prüfung updates.append({'range': f'{s_let}{row_num_in_sheet}', 'values': [["?"]]})
debug_print(f" -> Status S zurückgesetzt auf '?' für erneute Verifikation.") debug_print(f" -> Status S zurückgesetzt auf '?' für erneute Verifikation.")
else:
debug_print(f" -> FEHLER: Keine neuen Wiki-Daten extrahiert.")
# wiki_data behält die alten/default Werte
elif process_wiki: elif process_wiki:
debug_print(f"Zeile {row_num_in_sheet}: Überspringe Wikipedia Verarbeitung (Timestamp AN vorhanden UND S != 'X (URL Copied)').") debug_print(f"Zeile {row_num_in_sheet}: Überspringe Wikipedia Verarbeitung (AN vorhanden UND S != 'X (URL Copied)').")
# else: Wiki-Verarbeitung nicht aktiv
# --- 3. ChatGPT Evaluationen (Branch etc.) --- # --- 3. ChatGPT Evaluationen (Branch etc.) ---
# Trigger: AO fehlt ODER Wiki wurde gerade neu geparsed (um Branch neu zu bewerten) # Trigger: AO fehlt ODER Wiki wurde in DIESEM Lauf neu geparsed
chat_ts_ao_missing = not get_cell_value("Timestamp letzte Prüfung").strip() chat_ts_ao_missing = not get_cell_value("Timestamp letzte Prüfung").strip()
run_chat_eval = process_chatgpt and (chat_ts_ao_missing or reparse_wiki_needed) # reparse_wiki_needed ist True wenn Wiki neu gemacht wurde run_chat_eval = process_chatgpt and (chat_ts_ao_missing or wiki_data_updated_in_this_run) # <-- Nutze das neue Flag
if run_chat_eval: if run_chat_eval:
debug_print(f"Zeile {row_num_in_sheet}: Starte ChatGPT Evaluationen (Grund: AO fehlt? {chat_ts_ao_missing}, Wiki neu geparsed? {reparse_wiki_needed})...") debug_print(f"Zeile {row_num_in_sheet}: Starte ChatGPT Evaluationen (Grund: AO fehlt? {chat_ts_ao_missing}, Wiki gerade aktualisiert? {wiki_data_updated_in_this_run})...")
any_processing_done = True # Markiere, dass etwas getan wurde any_processing_done = True
# 3.1 Branchenevaluierung (Nutzt die ggf. gerade aktualisierten wiki_data) # 3.1 Branchenevaluierung (Nutzt IMMER die aktuelle 'wiki_data' Variable)
branch_result = evaluate_branche_chatgpt( branch_result = evaluate_branche_chatgpt(
crm_branche, crm_beschreibung, crm_branche, crm_beschreibung,
wiki_data.get('branche', 'k.A.'), # Nimmt aktuelle wiki_data wiki_data.get('branche', 'k.A.'), # Nimmt die potenziell neuen Daten
wiki_data.get('categories', 'k.A.'),# Nimmt aktuelle wiki_data wiki_data.get('categories', 'k.A.'),# Nimmt die potenziell neuen Daten
website_summary # Nimmt aktuellen website_summary website_summary
) )
updates.append({'range': f'W{row_num_in_sheet}', 'values': [[branch_result.get('branch', 'Fehler')]]}) updates.append({'range': f'W{row_num_in_sheet}', 'values': [[branch_result.get('branch', 'Fehler')]]})
updates.append({'range': f'X{row_num_in_sheet}', 'values': [[branch_result.get('consistency', 'Fehler')]]}) updates.append({'range': f'X{row_num_in_sheet}', 'values': [[branch_result.get('consistency', 'Fehler')]]})
updates.append({'range': f'Y{row_num_in_sheet}', 'values': [[branch_result.get('justification', 'Fehler')]]}) updates.append({'range': f'Y{row_num_in_sheet}', 'values': [[branch_result.get('justification', 'Fehler')]]})
# --- Hier weitere ChatGPT Evaluationen einfügen --- # ... (Hier weitere ChatGPT Evaluationen) ...
# ... (FSM, Mitarbeiter etc.) ...
# Setze Timestamp letzte Prüfung (AO) # Setze Timestamp letzte Prüfung (AO)
updates.append({'range': f'AO{row_num_in_sheet}', 'values': [[now_timestamp]]}) updates.append({'range': f'AO{row_num_in_sheet}', 'values': [[now_timestamp]]})
elif process_chatgpt: elif process_chatgpt:
debug_print(f"Zeile {row_num_in_sheet}: Überspringe ChatGPT Evaluationen (Timestamp AO vorhanden UND Wiki nicht neu geparsed).") debug_print(f"Zeile {row_num_in_sheet}: Überspringe ChatGPT Evaluationen (AO vorhanden UND Wiki nicht gerade aktualisiert).")
# --- 4. Abschließende Updates --- # --- 4. Abschließende Updates ---
if any_processing_done: if any_processing_done:
updates.append({'range': f'AP{row_num_in_sheet}', 'values': [[Config.VERSION]]}) # Setze Version nur wenn etwas getan wurde updates.append({'range': f'AP{row_num_in_sheet}', 'values': [[Config.VERSION]]})
# --- 5. Batch Update für diese Zeile durchführen --- # --- 5. Batch Update ---
if updates: if updates:
success = self.sheet_handler.batch_update_cells(updates) success = self.sheet_handler.batch_update_cells(updates)
if success: debug_print(f"Zeile {row_num_in_sheet}: Batch-Update erfolgreich ({len(updates)} Zellen/Bereiche).") if success: debug_print(f"Zeile {row_num_in_sheet}: Batch-Update erfolgreich ({len(updates)} Zellen/Bereiche).")
@@ -3370,7 +3353,7 @@ class DataProcessor:
debug_print(f"Zeile {row_num_in_sheet}: Keine Updates zum Schreiben.") debug_print(f"Zeile {row_num_in_sheet}: Keine Updates zum Schreiben.")
debug_print(f"--- Verarbeitung für Zeile {row_num_in_sheet} abgeschlossen ---") debug_print(f"--- Verarbeitung für Zeile {row_num_in_sheet} abgeschlossen ---")
time.sleep(max(0.1, Config.RETRY_DELAY / 20)) # Kürzere Pause, da Haupt-API Calls schon Pausen haben time.sleep(max(0.1, Config.RETRY_DELAY / 25)) # Noch kürzere Pause hier
def process_rows_sequentially(self, start_row_index, num_rows_to_process, process_wiki=True, process_chatgpt=True, process_website=True): def process_rows_sequentially(self, start_row_index, num_rows_to_process, process_wiki=True, process_chatgpt=True, process_website=True):