v1.2.4: Integrated ChatGPT API for Umsatz evaluation in Spalte AF
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.
This commit is contained in:
@@ -4,6 +4,7 @@ import re
|
|||||||
import gspread
|
import gspread
|
||||||
import wikipedia
|
import wikipedia
|
||||||
import requests
|
import requests
|
||||||
|
import openai
|
||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
from oauth2client.service_account import ServiceAccountCredentials
|
from oauth2client.service_account import ServiceAccountCredentials
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
@@ -13,7 +14,7 @@ import csv
|
|||||||
|
|
||||||
# ==================== KONFIGURATION ====================
|
# ==================== KONFIGURATION ====================
|
||||||
class Config:
|
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"
|
LANG = "de"
|
||||||
CREDENTIALS_FILE = "service_account.json"
|
CREDENTIALS_FILE = "service_account.json"
|
||||||
SHEET_URL = "https://docs.google.com/spreadsheets/d/1u_gHr9JUfmV1-iviRzbSe3575QEp7KLhK5jFV_gJcgo"
|
SHEET_URL = "https://docs.google.com/spreadsheets/d/1u_gHr9JUfmV1-iviRzbSe3575QEp7KLhK5jFV_gJcgo"
|
||||||
@@ -42,7 +43,6 @@ def debug_print(message):
|
|||||||
print(f"[DEBUG] {message}")
|
print(f"[DEBUG] {message}")
|
||||||
|
|
||||||
def clean_text(text):
|
def clean_text(text):
|
||||||
"""Normalisiert Unicode, entfernt Referenzen und extra Whitespace."""
|
|
||||||
if not text:
|
if not text:
|
||||||
return "k.A."
|
return "k.A."
|
||||||
text = unicodedata.normalize("NFKC", str(text))
|
text = unicodedata.normalize("NFKC", str(text))
|
||||||
@@ -72,14 +72,6 @@ def normalize_company_name(name):
|
|||||||
return normalized.lower()
|
return normalized.lower()
|
||||||
|
|
||||||
def extract_numeric_value(raw_value, is_umsatz=False):
|
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()
|
raw_value = raw_value.strip()
|
||||||
if not raw_value:
|
if not raw_value:
|
||||||
return "k.A."
|
return "k.A."
|
||||||
@@ -114,6 +106,39 @@ def extract_numeric_value(raw_value, is_umsatz=False):
|
|||||||
else:
|
else:
|
||||||
return str(int(round(num)))
|
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 ====================
|
# ==================== GOOGLE SHEET HANDLER ====================
|
||||||
class GoogleSheetHandler:
|
class GoogleSheetHandler:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@@ -131,9 +156,6 @@ class GoogleSheetHandler:
|
|||||||
|
|
||||||
# ==================== ALIGNMENT DEMO (Modus 3) ====================
|
# ==================== ALIGNMENT DEMO (Modus 3) ====================
|
||||||
def alignment_demo(sheet):
|
def alignment_demo(sheet):
|
||||||
"""
|
|
||||||
Alignment-Demo: Schreibt in Zeile 11200 die neuen Spaltenüberschriften gemäß dem neuen Schema.
|
|
||||||
"""
|
|
||||||
new_headers = [
|
new_headers = [
|
||||||
"Spalte A (ReEval Flag)",
|
"Spalte A (ReEval Flag)",
|
||||||
"Spalte B (Firmenname)",
|
"Spalte B (Firmenname)",
|
||||||
@@ -171,7 +193,7 @@ def alignment_demo(sheet):
|
|||||||
"Spalte AH (Timestamp letzte Prüfung)",
|
"Spalte AH (Timestamp letzte Prüfung)",
|
||||||
"Spalte AI (Version)"
|
"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)
|
sheet.update(values=[new_headers], range_name=header_range)
|
||||||
print("Alignment-Demo abgeschlossen: Neue Spaltenüberschriften in Zeile 11200 geschrieben.")
|
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}")
|
debug_print(f"Fehler beim Extrahieren des ersten Absatzes: {e}")
|
||||||
return "k.A."
|
return "k.A."
|
||||||
def extract_categories(self, soup):
|
def extract_categories(self, soup):
|
||||||
"""Extrahiert Wikipedia-Kategorien als kommagetrennten String."""
|
|
||||||
cat_div = soup.find('div', id="mw-normal-catlinks")
|
cat_div = soup.find('div', id="mw-normal-catlinks")
|
||||||
if cat_div:
|
if cat_div:
|
||||||
ul = cat_div.find('ul')
|
ul = cat_div.find('ul')
|
||||||
@@ -369,12 +390,15 @@ class DataProcessor:
|
|||||||
def _process_single_row(self, row_num, row_data):
|
def _process_single_row(self, row_num, row_data):
|
||||||
# Im neuen Schema: Firmenname in Spalte B (Index 1), Website in Spalte C (Index 2).
|
# Im neuen Schema: Firmenname in Spalte B (Index 1), Website in Spalte C (Index 2).
|
||||||
# Wikipedia-Daten werden in Spalten K bis Q geschrieben:
|
# 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.
|
# 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 ""
|
company_name = row_data[1] if len(row_data) > 1 else ""
|
||||||
website = row_data[2] if len(row_data) > 2 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}"
|
dt_range = f"AH{row_num}"
|
||||||
ver_range = f"AI{row_num}"
|
ver_range = f"AI{row_num}"
|
||||||
print(f"\n[{datetime.now().strftime('%H:%M:%S')}] Verarbeite Zeile {row_num}: {company_name}")
|
print(f"\n[{datetime.now().strftime('%H:%M:%S')}] Verarbeite Zeile {row_num}: {company_name}")
|
||||||
@@ -391,8 +415,7 @@ class DataProcessor:
|
|||||||
'categories': 'k.A.',
|
'categories': 'k.A.',
|
||||||
'full_infobox': 'k.A.'
|
'full_infobox': 'k.A.'
|
||||||
}
|
}
|
||||||
# Für Vorschlag Wiki URL setzen wir zunächst "k.A." als Platzhalter.
|
wiki_values = [
|
||||||
values = [
|
|
||||||
"k.A.", # Vorschlag Wiki URL
|
"k.A.", # Vorschlag Wiki URL
|
||||||
company_data.get('url', 'k.A.'),
|
company_data.get('url', 'k.A.'),
|
||||||
company_data.get('first_paragraph', 'k.A.'),
|
company_data.get('first_paragraph', 'k.A.'),
|
||||||
@@ -401,18 +424,27 @@ class DataProcessor:
|
|||||||
company_data.get('mitarbeiter', 'k.A.'),
|
company_data.get('mitarbeiter', 'k.A.'),
|
||||||
company_data.get('categories', '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")
|
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=[[current_dt]], range_name=dt_range)
|
||||||
self.sheet_handler.sheet.update(values=[[Config.VERSION]], range_name=ver_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":
|
if MODE == "2":
|
||||||
print("----- Vollständiger Infobox-Inhalt -----")
|
print("----- Vollständiger Infobox-Inhalt -----")
|
||||||
print(company_data.get("full_infobox", "k.A."))
|
print(company_data.get("full_infobox", "k.A."))
|
||||||
print("----------------------------------------")
|
print("----------------------------------------")
|
||||||
time.sleep(Config.RETRY_DELAY)
|
time.sleep(Config.RETRY_DELAY)
|
||||||
|
|
||||||
# ==================== MAIN ====================
|
|
||||||
if __name__ == "__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()
|
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":
|
if mode_input == "2":
|
||||||
|
|||||||
Reference in New Issue
Block a user