From ce7b830de2d60aa81ad895628b8d7f2328b0a1b3 Mon Sep 17 00:00:00 2001 From: Floke Date: Wed, 9 Apr 2025 12:07:18 +0000 Subject: [PATCH] =?UTF-8?q?v1.4.9:=20Verbesserte=20Wikipedia-Konsistenzpr?= =?UTF-8?q?=C3=BCfung=20und=20erweiterte=20Log-Ausgaben=20f=C3=BCr=20Websi?= =?UTF-8?q?te-Scraping?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Implementiert die Funktion is_valid_company_article(), die Wikipedia-Kategorien auf das Stichwort "unternehmen" (und Synonyme) überprüft. - In evaluate_branche_chatgpt() wird nun geprüft, ob Wiki-Kategorien "unternehmen" enthalten; falls nicht, wird die Website-Zusammenfassung als Fallback genutzt. - Debug-Ausgaben im Website-Scraping-Bereich (_process_single_row) wurden erweitert, um den extrahierten Rohtext (erste 100 Zeichen) aus Spalte AR und die Zusammenfassung in AS zu protokollieren. - Dies soll helfen, falsche Wikipedia-Artikel zu erkennen und den Fallback-Mechanismus zu verbessern. --- brancheneinstufung.py | 88 +++++++++++++++++++++++++++++-------------- 1 file changed, 60 insertions(+), 28 deletions(-) diff --git a/brancheneinstufung.py b/brancheneinstufung.py index cb5c7214..eb542e60 100644 --- a/brancheneinstufung.py +++ b/brancheneinstufung.py @@ -1,17 +1,19 @@ #!/usr/bin/env python3 """ -Version: v1.4.8 +Version: v1.4.9 Datum: {aktuelles Datum} Git-Überschrift (max. 100 Zeichen): -v1.4.8 Verbesserter Website-Scraper: User-Agent gesetzt und SSL-Verifikation optional +v1.4.9: Verbesserte Wikipedia-Konsistenzprüfung und erweiterte Log-Ausgaben für Website-Scraping Git-Änderungsbeschreibung: -- In get_website_raw() wurde ein User-Agent-Header hinzugefügt, um Blockaden zu vermeiden. -- SSL-Zertifikatüberprüfung kann jetzt optional durch den Parameter verify_cert deaktiviert werden (Standard: False). -- Zusätzliche Debug-Ausgaben protokollieren den Statuscode und erste 100 Zeichen des extrahierten Textes. -- Damit wird sichergestellt, dass beim Fehlen eines Wikipedia-Eintrags der Website-Fallback besser analysiert werden kann. - +- Implementiert die Funktion is_valid_company_article(), die Wikipedia-Kategorien auf + das Stichwort "unternehmen" (und Synonyme) überprüft. +- In evaluate_branche_chatgpt() wird nun geprüft, ob Wiki-Kategorien "unternehmen" enthalten; + falls nicht, wird die Website-Zusammenfassung als Fallback genutzt. +- Debug-Ausgaben im Website-Scraping-Bereich (_process_single_row) wurden erweitert, + um den extrahierten Rohtext (erste 100 Zeichen) aus Spalte AR und die Zusammenfassung in AS zu protokollieren. +- Dies soll helfen, falsche Wikipedia-Artikel zu erkennen und den Fallback-Mechanismus zu verbessern. """ @@ -37,7 +39,7 @@ except ImportError: # ==================== KONFIGURATION ==================== class Config: - VERSION = "v1.4.8" + VERSION = "v1.4.9" LANG = "de" CREDENTIALS_FILE = "service_account.json" SHEET_URL = "https://docs.google.com/spreadsheets/d/1u_gHr9JUfmV1-iviRzbSe3575QEp7KLhK5jFV_gJcgo" @@ -98,6 +100,27 @@ def simple_normalize_url(url): except Exception as e: return "k.A." +def is_valid_company_article(wiki_categories): + """ + Prüft, ob in den Wikipedia-Kategorien ein Hinweis auf einen Unternehmensartikel enthalten ist. + Wir suchen nach den Stichwörtern 'unternehmen', 'firma', 'betrieb' und 'konzern'. + + Args: + wiki_categories (str): Die Liste oder der String der Wikipedia-Kategorien. + + Returns: + bool: True, wenn eines der Keywords gefunden wird, sonst False. + """ + if wiki_categories == "k.A.": + return False + keywords = ["unternehmen", "firma", "betrieb", "konzern"] + wiki_cats_lower = wiki_categories.lower() + for word in keywords: + if word in wiki_cats_lower: + return True + return False + + def serp_website_lookup(company_name): """ Ermittelt über SERPAPI (Google-Suche) die Website zum Unternehmen. @@ -971,6 +994,22 @@ class WikipediaScraper: # ==================== NEUE FUNKTION: Angepasste evaluate_branche_chatgpt ==================== def evaluate_branche_chatgpt(crm_branche, beschreibung, wiki_branche, wiki_kategorien, website_summary): + """ + Ordnet basierend auf den angegebenen Daten das Unternehmen exakt einer Branche aus dem Ziel-Branchenschema zu. + Falls kein passender Wikipedia-Artikel vorliegt bzw. die Kategorien nicht aussagekräftig sind + (d.h. das Stichwort 'unternehmen' fehlt), wird die Website-Zusammenfassung als Fallback genutzt. + + Args: + crm_branche (str): Branche aus CRM-Daten (Spalte F). + beschreibung (str): Externe oder CRM-Beschreibung (Spalte G). + wiki_branche (str): Wikipedia-Branche (Spalte N). + wiki_kategorien (str): Wikipedia-Kategorien (Spalte Q). + website_summary (str): Zusammenfassung des Website-Contents als Fallback. + + Returns: + dict: {"branch": , "consistency": <"ok" oder "X">, "justification": } + """ + # Hilfsfunktion zum Laden des Ziel-Branchenschemas def load_target_branches(): try: with open("ziel_Branchenschema.csv", "r", encoding="utf-8") as csvfile: @@ -980,6 +1019,7 @@ def evaluate_branche_chatgpt(crm_branche, beschreibung, wiki_branche, wiki_kateg except Exception as e: debug_print(f"Fehler beim Laden des Ziel-Branchenschemas: {e}") return [] + target_branches = load_target_branches() target_branches_str = "\n".join(target_branches) focus_branches = [ @@ -1000,17 +1040,10 @@ def evaluate_branche_chatgpt(crm_branche, beschreibung, wiki_branche, wiki_kateg "Versorger > Telekommunikation" ] focus_branches_str = "\n".join(focus_branches) - try: - with open("api_key.txt", "r") as f: - api_key = f.read().strip() - except Exception as e: - debug_print(f"Fehler beim Lesen des API-Tokens (Branche): {e}") - return {"branch": "k.A.", "consistency": "k.A.", "justification": "k.A."} - openai.api_key = api_key - - # Angepasst: Sobald kein Wikipedia-Artikel (Wiki-Branche) vorhanden ist, wird die Website-Zusammenfassung als Fallback genutzt. - if wiki_branche.strip().lower() == "k.a.": - debug_print("Kein Wikipedia-Artikel vorhanden – verwende Website-Zusammenfassung als Branchenbeschreibung-Fallback.") + + # Wenn kein Wikipedia-Artikel vorhanden oder die Kategorien nicht aussagekräftig sind, fallback auf die Website-Zusammenfassung. + if wiki_branche.strip().lower() == "k.a." or not is_valid_company_article(wiki_kategorien): + debug_print("Keine aussagekräftigen Wikipedia-Kategorien – verwende Website-Zusammenfassung als Fallback.") used_description = website_summary else: used_description = beschreibung @@ -1038,7 +1071,7 @@ def evaluate_branche_chatgpt(crm_branche, beschreibung, wiki_branche, wiki_kateg try: response = openai.ChatCompletion.create( - model="gpt-3.5-turbo", + model=Config.TOKEN_MODEL, messages=[{"role": "system", "content": system_prompt}], temperature=0.0 ) @@ -1068,6 +1101,7 @@ def evaluate_branche_chatgpt(crm_branche, beschreibung, wiki_branche, wiki_kateg return {"branch": "k.A.", "consistency": "k.A.", "justification": "k.A."} + def evaluate_servicetechnicians_estimate(company_name, company_data): try: with open("serpApiKey.txt", "r") as f: @@ -1219,25 +1253,23 @@ def _process_single_row(self, row_num, row_data, process_wiki=True, process_chat website_raw = "k.A." website_summary = "k.A." if website_url.strip() != "" and website_url.strip().lower() != "k.a.": - # Extrahiere den Rohtext der Website website_raw = get_website_raw(website_url) - # Erstelle eine Zusammenfassung des Website-Contents website_summary = summarize_website_content(website_raw) try: self.sheet_handler.sheet.update(values=[[website_raw]], range_name=f"AR{row_num}") - debug_print(f"Zeile {row_num}: Spalte AR Update erfolgreich.") + debug_print(f"Zeile {row_num}: Spalte AR Update erfolgreich – Auszug: {website_raw[:100]}...") except Exception as e: debug_print(f"Zeile {row_num}: Fehler beim Update von Spalte AR: {e}") try: self.sheet_handler.sheet.update(values=[[website_summary]], range_name=f"AS{row_num}") - debug_print(f"Zeile {row_num}: Spalte AS Update erfolgreich.") + debug_print(f"Zeile {row_num}: Spalte AS Update erfolgreich – Zusammenfassung: {website_summary}") except Exception as e: debug_print(f"Zeile {row_num}: Fehler beim Update von Spalte AS: {e}") - debug_print(f"Zeile {row_num}: Website-Daten gescrapt. Rohtext (Länge {len(website_raw)}): {website_raw[:100]}..., Zusammenfassung: {website_summary}") + debug_print(f"Zeile {row_num}: Website-Daten gescrapt. Rohtext Länge: {len(website_raw)}, Zusammenfassung: {website_summary}") else: debug_print(f"Zeile {row_num}: Kein gültiger Website-URL vorhanden, Website-Scraping wird übersprungen.") - # Weiterer Verarbeitungsteil: Wikipedia-Verarbeitung (falls process_wiki True) + # Wikipedia-Verarbeitung (falls process_wiki True) wiki_update_range = f"L{row_num}:R{row_num}" dt_wiki_range = f"AN{row_num}" company_data = {} @@ -1308,14 +1340,13 @@ def _process_single_row(self, row_num, row_data, process_wiki=True, process_chat self.sheet_handler.sheet.update(values=[[emp_consistency]], range_name=f"AC{row_num}") revenue_result = evaluate_umsatz_chatgpt(company_name, company_data.get('umsatz', 'k.A.')) self.sheet_handler.sheet.update(values=[[revenue_result]], range_name=f"AG{row_num}") - # Hier NICHT mehr neu einlesen! Verwende die bereits extrahierten Website-Daten. total_tokens = f"Wiki: {token_count(str(company_data.get('first_paragraph', '')))}, Chat: {token_count(crm_data + wiki_data_str)}, Emp: {token_count(str(emp_estimate))}" self.sheet_handler.sheet.update(values=[[total_tokens]], range_name=f"AQ{row_num}") self.sheet_handler.sheet.update(values=[[datetime.now().strftime('%Y-%m-%d %H:%M:%S')]], range_name=dt_chat_range) else: debug_print(f"Zeile {row_num}: ChatGPT-Timestamp bereits gesetzt – überspringe ChatGPT-Auswertung.") - # Aktualisiere den Timestamp für die letzte Prüfung und die Version + # Aktualisiere Timestamp und Version current_dt = datetime.now().strftime("%Y-%m-%d %H:%M:%S") self.sheet_handler.sheet.update(values=[[current_dt]], range_name=ver_range) self.sheet_handler.sheet.update(values=[[Config.VERSION]], range_name=ver_range) @@ -1327,6 +1358,7 @@ def _process_single_row(self, row_num, row_data, process_wiki=True, process_chat + # ==================== ALIGNMENT DEMO FÜR HAUPTBLATT UND CONTACTS ==================== def alignment_demo_full():