From 1a2a81fa4ba52cd0ca1a52180dfbf3348e98e78a Mon Sep 17 00:00:00 2001 From: Floke Date: Tue, 1 Apr 2025 16:52:29 +0000 Subject: [PATCH] v1.2.4: Integrated ChatGPT API for Umsatz evaluation in Spalte AF MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ChatGPT API Integration: Neue Funktion evaluate_umsatz_chatgpt liest den API-Token aus der Datei api_key.txt und sendet einen strukturierten Prompt an die ChatGPT API. Der Prompt fordert zur Schätzung des Umsatzes in Mio. Euro auf Basis des Unternehmensnamens und der Wikipedia-Umsatzangabe auf. Das Ergebnis (nur eine Zahl) wird verarbeitet und in Spalte AF (Schätzung Umsatz ChatGPT) eingetragen. Update der DataProcessor-Logik: Nach der Aktualisierung der Wikipedia-Daten (Spalten K bis Q) wird die ChatGPT-API-Funktion aufgerufen, um den Umsatz zu evaluieren, und das Ergebnis in Spalte AF geschrieben. --- brancheneinstufung.py | 78 ++++++++++++++++++++++++++++++------------- 1 file changed, 55 insertions(+), 23 deletions(-) diff --git a/brancheneinstufung.py b/brancheneinstufung.py index 6ba3d94c..17a2e975 100644 --- a/brancheneinstufung.py +++ b/brancheneinstufung.py @@ -4,6 +4,7 @@ import re import gspread import wikipedia import requests +import openai from bs4 import BeautifulSoup from oauth2client.service_account import ServiceAccountCredentials from datetime import datetime @@ -13,7 +14,7 @@ import csv # ==================== KONFIGURATION ==================== class Config: - VERSION = "v1.2.3" # v1.2.3: Neue Spaltenzuordnung gemäß dem neuen Schema, Wikipedia-Kategorien extrahieren + VERSION = "v1.2.4" # v1.2.4: Integriert ChatGPT API zur Umsatzbewertung in Spalte AF LANG = "de" CREDENTIALS_FILE = "service_account.json" SHEET_URL = "https://docs.google.com/spreadsheets/d/1u_gHr9JUfmV1-iviRzbSe3575QEp7KLhK5jFV_gJcgo" @@ -42,7 +43,6 @@ def debug_print(message): print(f"[DEBUG] {message}") def clean_text(text): - """Normalisiert Unicode, entfernt Referenzen und extra Whitespace.""" if not text: return "k.A." text = unicodedata.normalize("NFKC", str(text)) @@ -72,14 +72,6 @@ def normalize_company_name(name): return normalized.lower() def extract_numeric_value(raw_value, is_umsatz=False): - """ - Extrahiert den numerischen Wert aus raw_value. - - Nutzt Komma als Dezimaltrenner und entfernt Punkte als Tausendertrennzeichen. - - Für Umsatz: Falls "mrd" vorkommt, wird der Wert mit 1000 multipliziert; - enthält der Text keine Einheit, so wird durch 1e6 geteilt. - - Für Mitarbeiter: Gibt den ganzzahligen Wert zurück. - - Bei Fehlern wird der Original-Rohtext im Debug-Log ausgegeben. - """ raw_value = raw_value.strip() if not raw_value: return "k.A." @@ -114,6 +106,39 @@ def extract_numeric_value(raw_value, is_umsatz=False): else: return str(int(round(num))) +def evaluate_umsatz_chatgpt(company_name, wiki_umsatz): + """ + Sendet einen strukturierten Prompt an die ChatGPT API, um den Umsatz (in Mio. €) zu evaluieren. + Liest den API-Token aus der Datei "api_key.txt". + Erwartet als Antwort eine Zahl (Mio. €). + """ + 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: {e}") + return "k.A." + openai.api_key = api_key + prompt = (f"Bitte schätze den Umsatz in Mio. Euro für das Unternehmen '{company_name}'. " + f"Die Wikipedia-Daten zeigen: '{wiki_umsatz}'. " + "Antworte nur mit der Zahl.") + try: + response = openai.ChatCompletion.create( + model="gpt-3.5-turbo", + messages=[{"role": "user", "content": prompt}], + temperature=0.0 + ) + result = response.choices[0].message.content.strip() + try: + value = float(result.replace(',', '.')) + return str(int(round(value))) + except Exception as conv_e: + debug_print(f"Fehler bei der Verarbeitung der ChatGPT-Antwort '{result}': {conv_e}") + return result + except Exception as e: + debug_print(f"Fehler beim Aufruf der ChatGPT API: {e}") + return "k.A." + # ==================== GOOGLE SHEET HANDLER ==================== class GoogleSheetHandler: def __init__(self): @@ -131,9 +156,6 @@ class GoogleSheetHandler: # ==================== ALIGNMENT DEMO (Modus 3) ==================== def alignment_demo(sheet): - """ - Alignment-Demo: Schreibt in Zeile 11200 die neuen Spaltenüberschriften gemäß dem neuen Schema. - """ new_headers = [ "Spalte A (ReEval Flag)", "Spalte B (Firmenname)", @@ -171,7 +193,7 @@ def alignment_demo(sheet): "Spalte AH (Timestamp letzte Prüfung)", "Spalte AI (Version)" ] - header_range = "A11200:AI11200" # 35 Spalten: A bis AI + header_range = "A11200:AI11200" sheet.update(values=[new_headers], range_name=header_range) print("Alignment-Demo abgeschlossen: Neue Spaltenüberschriften in Zeile 11200 geschrieben.") @@ -245,7 +267,6 @@ class WikipediaScraper: debug_print(f"Fehler beim Extrahieren des ersten Absatzes: {e}") return "k.A." def extract_categories(self, soup): - """Extrahiert Wikipedia-Kategorien als kommagetrennten String.""" cat_div = soup.find('div', id="mw-normal-catlinks") if cat_div: ul = cat_div.find('ul') @@ -369,12 +390,15 @@ class DataProcessor: def _process_single_row(self, row_num, row_data): # Im neuen Schema: Firmenname in Spalte B (Index 1), Website in Spalte C (Index 2). # Wikipedia-Daten werden in Spalten K bis Q geschrieben: - # K: Vorschlag Wiki URL, L: Wikipedia URL, M: Wikipedia Absatz, N: Wikipedia Branche, + # K: Vorschlag Wiki URL (Platzhalter "k.A.") + # L: Wikipedia URL, M: Wikipedia Absatz, N: Wikipedia Branche, # O: Wikipedia Umsatz, P: Wikipedia Mitarbeiter, Q: Wikipedia Kategorien. - # Timestamp (jetzt) in Spalte AH, Version in Spalte AI. + # ChatGPT Umsatz wird in Spalte AF geschrieben. + # Timestamp in Spalte AH, Version in Spalte AI. company_name = row_data[1] if len(row_data) > 1 else "" website = row_data[2] if len(row_data) > 2 else "" - update_range = f"K{row_num}:Q{row_num}" + wiki_update_range = f"K{row_num}:Q{row_num}" + chatgpt_range = f"AF{row_num}" dt_range = f"AH{row_num}" ver_range = f"AI{row_num}" print(f"\n[{datetime.now().strftime('%H:%M:%S')}] Verarbeite Zeile {row_num}: {company_name}") @@ -391,8 +415,7 @@ class DataProcessor: 'categories': 'k.A.', 'full_infobox': 'k.A.' } - # Für Vorschlag Wiki URL setzen wir zunächst "k.A." als Platzhalter. - values = [ + wiki_values = [ "k.A.", # Vorschlag Wiki URL company_data.get('url', 'k.A.'), company_data.get('first_paragraph', 'k.A.'), @@ -401,18 +424,27 @@ class DataProcessor: company_data.get('mitarbeiter', 'k.A.'), company_data.get('categories', 'k.A.') ] - self.sheet_handler.sheet.update(values=[values], range_name=update_range) + self.sheet_handler.sheet.update(values=[wiki_values], range_name=wiki_update_range) + # ChatGPT API: Umsatzbewertung basierend auf Firmenname und Wikipedia-Umsatz + wiki_umsatz = company_data.get('umsatz', 'k.A.') + if wiki_umsatz != "k.A.": + chatgpt_umsatz = evaluate_umsatz_chatgpt(company_name, wiki_umsatz) + else: + chatgpt_umsatz = "k.A." + self.sheet_handler.sheet.update(values=[[chatgpt_umsatz]], range_name=chatgpt_range) current_dt = datetime.now().strftime("%Y-%m-%d %H:%M:%S") self.sheet_handler.sheet.update(values=[[current_dt]], range_name=dt_range) self.sheet_handler.sheet.update(values=[[Config.VERSION]], range_name=ver_range) - print(f"✅ Aktualisiert: URL: {company_data.get('url', 'k.A.')}, Absatz: {company_data.get('first_paragraph', 'k.A.')[:30]}..., Branche: {company_data.get('branche', 'k.A.')}, Umsatz: {company_data.get('umsatz', 'k.A.')}, Mitarbeiter: {company_data.get('mitarbeiter', 'k.A.')}, Kategorien: {company_data.get('categories', 'k.A.')}") + print(f"✅ Aktualisiert: URL: {company_data.get('url', 'k.A.')}, Absatz: {company_data.get('first_paragraph', 'k.A.')[:30]}..., " + f"Branche: {company_data.get('branche', 'k.A.')}, Wikipedia Umsatz: {company_data.get('umsatz', 'k.A.')}, " + f"Mitarbeiter: {company_data.get('mitarbeiter', 'k.A.')}, Kategorien: {company_data.get('categories', 'k.A.')}, " + f"ChatGPT Umsatz: {chatgpt_umsatz}") if MODE == "2": print("----- Vollständiger Infobox-Inhalt -----") print(company_data.get("full_infobox", "k.A.")) print("----------------------------------------") time.sleep(Config.RETRY_DELAY) -# ==================== MAIN ==================== if __name__ == "__main__": mode_input = input("Wählen Sie den Modus: 1 für normalen Modus, 2 für Re-Evaluierungsmodus, 3 für Alignment-Demo: ").strip() if mode_input == "2":