v1.3.1: Validierung des Wikipedia-Artikels implementiert

Validierungsschritt:
Die neue Funktion validate_article_with_chatgpt(crm_data, wiki_data) aggregiert die CRM-Daten (Spalten B–J) und die Wikipedia-Daten (Spalten L–Q) als CSV-Text. Der erstellte Prompt teilt ChatGPT mit, dass beide Datensätze verglichen werden sollen, um zu prüfen, ob sie zum selben Unternehmen gehören.
– Wichtige Vergleichskriterien sind der Firmenname, Ort und Branche (die Umsatzangaben können toleriert werden).
– Das Ergebnis (z. B. "OK" oder eine Begründung) wird in Spalte R (Konsistenzprüfung) gespeichert.

Integration:
Der Validierungsschritt wird direkt in _process_single_row nach dem Aktualisieren der Wikipedia-Daten ausgeführt. Eine 1‑Sekunden-Pause wurde eingebaut, um sicherzustellen, dass die Daten in Google Sheets aktualisiert sind, bevor die Validierung erfolgt.

Logging:
Ausführliche Debug-Ausgaben helfen dabei, den Vergleich und eventuelle Fehler zu überwachen.
This commit is contained in:
2025-04-02 08:55:47 +00:00
parent eb25486c2a
commit c6836d0c2a

View File

@@ -14,7 +14,7 @@ import csv
# ==================== KONFIGURATION ====================
class Config:
VERSION = "v1.3.0" # v1.3.0: Neue Spaltenzuordnung, verbesserte numerische Extraktion & 1 Sekunde Pause
VERSION = "v1.3.1" # v1.3.1: Validierung des Wikipedia-Artikels implementiert
LANG = "de"
CREDENTIALS_FILE = "service_account.json"
SHEET_URL = "https://docs.google.com/spreadsheets/d/1u_gHr9JUfmV1-iviRzbSe3575QEp7KLhK5jFV_gJcgo"
@@ -72,18 +72,16 @@ def normalize_company_name(name):
return normalized.lower()
def extract_numeric_value(raw_value, is_umsatz=False):
raw_value = unicodedata.normalize("NFKC", raw_value.strip())
raw_value = raw_value.strip()
if not raw_value:
return "k.A."
# Entferne gängige Zusätze wie "ca.", "circa", "über" etc.
raw_value = re.sub(r'\b(ca\.?|circa|über)\b', '', raw_value, flags=re.IGNORECASE)
raw = raw_value.lower().replace("\xa0", " ")
# Robustere Regex: Erfasst Ziffern, optionale Dezimaltrennzeichen
match = re.search(r'([\d]+(?:[.,]\d+)*)', raw, flags=re.UNICODE)
match = re.search(r'([\d.,]+)', raw, flags=re.UNICODE)
if not match or not match.group(1).strip():
debug_print(f"Keine numerischen Zeichen gefunden im Rohtext: '{raw_value}'")
return "k.A."
num_str = unicodedata.normalize("NFKC", match.group(1))
num_str = match.group(1)
if ',' in num_str:
num_str = num_str.replace('.', '').replace(',', '.')
try:
@@ -134,9 +132,11 @@ def evaluate_umsatz_chatgpt(company_name, wiki_umsatz):
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.")
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",
@@ -155,6 +155,45 @@ def evaluate_umsatz_chatgpt(company_name, wiki_umsatz):
debug_print(f"Fehler beim Aufruf der ChatGPT API: {e}")
return "k.A."
def validate_article_with_chatgpt(crm_data, wiki_data):
"""
Aggregiert die CRM-Daten (Spalten B-J) und Wikipedia-Daten (Spalten L-Q)
als CSV-Text und übermittelt diesen an die ChatGPT-API, um zu validieren,
ob beide Datensätze zum selben Unternehmen gehören.
"""
# Erstelle den CSV-Text
crm_headers = "Firmenname;Website;Ort;Beschreibung;Aktuelle Branche;Beschreibung Branche extern;Anzahl Techniker;Umsatz (CRM);Anzahl Mitarbeiter (CRM)"
wiki_headers = "Wikipedia URL;Wikipedia Absatz;Wikipedia Branche;Wikipedia Umsatz;Wikipedia Mitarbeiter;Wikipedia Kategorien"
prompt_text = (
"Bitte überprüfe, ob die folgenden beiden Datensätze zum gleichen Unternehmen gehören. "
"Die erste Zeile sind Daten aus unserem CRM-System, die zweite Zeile stammen aus Wikipedia. "
"Vergleiche insbesondere den Firmennamen, den Ort und die Branche. Unterschiede im Umsatz können toleriert werden, "
"solange sie im Rahmen von 10% liegen. Falls die Datensätze übereinstimmen, antworte ausschließlich mit 'OK'. "
"Falls nicht, nenne bitte den wichtigsten Grund (z.B. abweichender Firmenname oder Ort). \n\n"
f"CRM-Daten:\n{crm_headers}\n{crm_data}\n\n"
f"Wikipedia-Daten:\n{wiki_headers}\n{wiki_data}\n\n"
"Antwort: "
)
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
try:
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[{"role": "system", "content": prompt_text}],
temperature=0.0
)
result = response.choices[0].message.content.strip()
debug_print(f"Validierungsantwort ChatGPT: '{result}'")
return result
except Exception as e:
debug_print(f"Fehler beim Validierungs-API-Aufruf: {e}")
return "k.A."
# ==================== GOOGLE SHEET HANDLER ====================
class GoogleSheetHandler:
def __init__(self):
@@ -334,8 +373,15 @@ class WikipediaScraper:
return result
def extract_company_data(self, page_url):
if not page_url:
return {'url': 'k.A.', 'first_paragraph': 'k.A.', 'branche': 'k.A.',
'umsatz': 'k.A.', 'mitarbeiter': 'k.A.', 'categories': 'k.A.', 'full_infobox': 'k.A.'}
return {
'url': 'k.A.',
'first_paragraph': 'k.A.',
'branche': 'k.A.',
'umsatz': 'k.A.',
'mitarbeiter': 'k.A.',
'categories': 'k.A.',
'full_infobox': 'k.A.'
}
try:
response = requests.get(page_url)
soup = BeautifulSoup(response.text, Config.HTML_PARSER)
@@ -359,8 +405,15 @@ class WikipediaScraper:
}
except Exception as e:
debug_print(f"Extraktionsfehler: {str(e)}")
return {'url': 'k.A.', 'first_paragraph': 'k.A.', 'branche': 'k.A.',
'umsatz': 'k.A.', 'mitarbeiter': 'k.A.', 'categories': 'k.A.', 'full_infobox': 'k.A.'}
return {
'url': 'k.A.',
'first_paragraph': 'k.A.',
'branche': 'k.A.',
'umsatz': 'k.A.',
'mitarbeiter': 'k.A.',
'categories': 'k.A.',
'full_infobox': 'k.A.'
}
@retry_on_failure
def search_company_article(self, company_name, website):
search_terms = self._generate_search_terms(company_name, website)
@@ -404,18 +457,14 @@ class DataProcessor:
if i >= self.sheet_handler.get_start_index():
self._process_single_row(i, row)
def _process_single_row(self, row_num, row_data):
# Neues Schema:
# Spalte B: Firmenname, Spalte C: Website
# Wikipedia-Daten: Spalten K bis Q
# ChatGPT Umsatz: Spalte AF
# CRM Umsatz in Spalte I (Index 8)
# Umsatz-Abgleich: Spalte AG
# Timestamp in Spalte AH, Version in Spalte AI.
# CRM-Daten: Spalten B bis J (Indices 1 bis 9)
# Wikipedia-Daten: Spalten L bis Q (Indices 11 bis 16)
company_name = row_data[1] if len(row_data) > 1 else ""
website = row_data[2] if len(row_data) > 2 else ""
wiki_update_range = f"K{row_num}:Q{row_num}"
chatgpt_range = f"AF{row_num}"
abgleich_range = f"AG{row_num}"
valid_range = f"R{row_num}" # Konsistenzprüfung
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}")
@@ -442,26 +491,32 @@ class DataProcessor:
company_data.get('categories', 'k.A.')
]
self.sheet_handler.sheet.update(values=[wiki_values], range_name=wiki_update_range)
# 1 Sekunde Pause, um sicherzustellen, dass die Daten in Google Sheets gespeichert wurden.
time.sleep(1)
# ChatGPT API: Umsatzbewertung basierend auf Firmenname und Wikipedia-Umsatz
# Umsatz-Schätzung via ChatGPT (wie bisher)
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)
# Umsatz-Abgleich: CRM-Umsatz aus Spalte I und Wikipedia-Umsatz
# Umsatz-Abgleich (wie bisher)
crm_umsatz = row_data[8] if len(row_data) > 8 else "k.A."
abgleich_result = compare_umsatz_values(crm_umsatz, company_data.get('umsatz', 'k.A.'))
self.sheet_handler.sheet.update(values=[[abgleich_result]], range_name=abgleich_range)
# --- Neuer Validierungsschritt ---
# Aggregiere CRM-Daten (B bis J) und Wikipedia-Daten (L bis Q) als CSV-Text
crm_data = ";".join(row_data[1:10])
wiki_data = ";".join(row_data[11:17])
valid_result = validate_article_with_chatgpt(crm_data, wiki_data)
self.sheet_handler.sheet.update(values=[[valid_result]], range_name=valid_range)
# Timestamp und Version schreiben
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]}..., "
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}, Umsatz-Abgleich: {abgleich_result}")
f"ChatGPT Umsatz: {chatgpt_umsatz}, Umsatz-Abgleich: {abgleich_result}, Validierung: {valid_result}")
if MODE == "2":
print("----- Vollständiger Infobox-Inhalt -----")
print(company_data.get("full_infobox", "k.A."))