Deepseek Aktualisierung

This commit is contained in:
2025-03-30 12:38:39 +00:00
parent 3da57a95ca
commit 70b47d65d4

View File

@@ -2,7 +2,6 @@ import os
import time
import csv
import re
import pandas as pd
import gspread
import openai
import wikipedia
@@ -21,202 +20,169 @@ DURCHLÄUFE = int(input("Wieviele Zeilen sollen überprüft werden? "))
MAX_RETRIES = 3
RETRY_DELAY = 5
# === OpenAI API-KEY LADEN ===
# === OpenAI INIT ===
with open("api_key.txt", "r") as f:
openai.api_key = f.read().strip()
# === GOOGLE SHEET VERBINDUNG ===
# === GOOGLE SHEETS ===
scope = ["https://www.googleapis.com/auth/spreadsheets"]
creds = ServiceAccountCredentials.from_json_keyfile_name(CREDENTIALS, scope)
sheet = gspread.authorize(creds).open_by_url(SHEET_URL).sheet1
client = gspread.authorize(creds)
sheet = client.open_by_url(SHEET_URL).sheet1
sheet_values = sheet.get_all_values()
# === STARTINDEX SUCHEN (Spalte N = Index 13) ===
filled_n = [row[13] if len(row) > 13 else '' for row in sheet_values[1:]]
start = next((i + 1 for i, v in enumerate(filled_n, start=1) if not str(v).strip()), len(filled_n) + 1)
print(f"Starte bei Zeile {start+1}")
# === WIKIPEDIA KONFIG ===
wikipedia.set_lang(LANG)
WHITELIST_KATEGORIEN = [
"unternehmen", "hersteller", "produktion", "industrie",
"maschinenbau", "technik", "dienstleistung", "chemie",
"pharma", "elektro", "medizin", "bau", "energie",
"logistik", "automobil", "handel", "textil", "klima"
]
# === SYSTEM PROMPT ===
branches = [
"Hersteller / Produzenten > Maschinenbau",
# ... (restliche Branchen wie zuvor)
"Gutachter / Versicherungen > Medizinische Gutachten"
]
branches = [...] # Branchenliste hier einfügen
system_prompt = {
"role": "system",
"content": (
"Du bist ein Experte für Brancheneinstufung und FSM-Potenzialbewertung. "
"Bitte beziehe dich ausschließlich auf das konkret genannte Unternehmen. Ähnlich klingende Firmennamen dürfen nicht verwendet werden.\n"
"FSM steht für Field Service Management Software zur Planung und Unterstützung mobiler Techniker.\n"
"Ziel ist es, Unternehmen mit >50 Technikern im Außeneinsatz zu identifizieren.\n\n"
"Struktur: Firmenname; Website; Ort; Aktuelle Einstufung; Beschreibung der Branche Extern\n\n"
"Gib deine Antwort im CSV-Format (1 Zeile, 8 Spalten, durch Semikolon getrennt):\n"
"Wikipedia-Branche;LinkedIn-Branche;Umsatz (Mio €);Empfohlene Neueinstufung;Begründung;FSM-Relevanz (Ja/Nein/k.A. mit Begründung);Techniker-Einschätzung;Techniker-Begründung\n\n"
"Falls ein Wikipedia-Link angegeben ist, vertraue ausschließlich den Angaben aus diesem Artikel für Branche und Umsatz.\n"
"Falls kein Wikipedia-Link existiert, gib für 'Wikipedia-Branche' und 'Umsatz (Mio €)' bitte 'k.A.' aus.\n\n"
"Ziel-Branchenschema:\n" + "\n".join(branches)
"Du bist ein Experte für Brancheneinstufung. Beantworte ausschließlich "
"basierend auf den gegebenen Unternehmensdaten. Format: "
"Wikipedia-Branche;LinkedIn-Branche;Umsatz (Mio €);Empfohlene Neueinstufung;"
"Begründung;FSM-Relevanz;Techniker-Einschätzung;Techniker-Begründung"
)
}
WHITELIST_KATEGORIEN = ["unternehmen", "hersteller", "produktion", "industrie",
"maschinenbau", "technik", "dienstleistungsunternehmen",
"chemie", "pharma", "elektrotechnik", "medizintechnik"]
def extract_domain_key(url):
"""Extrahiert den Domain-Schlüssel aus der Website-URL"""
if not url:
return ""
clean_url = url.replace("https://", "").replace("http://", "").split("/")[0]
parts = clean_url.split(".")
return parts[0] if len(parts) > 1 else ""
# === HELFERFUNKTIONEN ===
def extract_domain(url):
"""Extrahiert den Domain-Schlüssel aus der URL"""
if not url.startswith("http"):
url = f"https://{url}"
return url.split("//")[-1].split("/")[0].split(".")[0]
def validate_wikipedia_content(content, name, domain):
"""Prüft ob der Artikel zum Unternehmen gehört"""
name_fragments = name.lower().split()[:2]
return (
any(frag in content.lower() for frag in name_fragments) or
(domain and domain.lower() in content.lower())
def parse_infobox(soup):
"""Extrahiert Branche und Umsatz aus der Wikipedia-Infobox"""
infobox = soup.find("table", class_=["infobox", "infobox vcard"])
"""Extrahiert Branche und Umsatz aus der Infobox"""
branche = umsatz = ""
if infobox:
for row in infobox.find_all("tr"):
th = row.find("th")
td = row.find("td")
if not th or not td:
continue
for row in soup.find_all("tr"):
th = row.find("th")
td = row.find("td")
if not th or not td:
continue
# Branchenerkennung
if "branche" in th.text.lower():
branche = td.get_text(separator=" ", strip=True)
# Umsatzerkennung
if "umsatz" in th.text.lower():
umsatz_text = td.get_text(strip=True)
if "Mio" in umsatz_text:
match = re.search(r"(\d+[\d.,]*)\s*Mio", umsatz_text)
if match:
umsatz = match.group(1).replace(",", ".")
header = th.get_text(strip=True).lower()
value = td.get_text(separator=" ", strip=True)
# Branche erkennen
if any(s in header for s in ["branche", "industrie", "tätigkeitsfeld"]):
branche = value
# Umsatz erkennen
if "umsatz" in header:
if "mio" in value.lower():
match = re.search(r"(\d{1,3}(?:[.,]\d{3})*(?:[.,]\d+)?)", value)
if match:
umsatz = match.group(1).replace(",", ".")
return branche, umsatz
def get_wikipedia_data(name, website_hint=""):
"""Sucht Wikipedia-Daten mit erweiterter Validierung"""
domain_key = extract_domain_key(website_hint)
search_terms = [name, domain_key] if domain_key else [name]
def get_wikipedia_data(name, website):
"""Holt validierte Wikipedia-Daten"""
domain = extract_domain(website) if website else ""
for term in search_terms:
if not term:
continue
for attempt in range(MAX_RETRIES):
try:
results = wikipedia.search(term, results=3)
for title in results:
try:
page = wikipedia.page(title, auto_suggest=False)
html = requests.get(page.url, timeout=10).text
# Validierung der Übereinstimmung
content_check = (
name.split()[0].lower() in page.content.lower() or
(domain_key and domain_key.lower() in html.lower())
)
if content_check:
soup = BeautifulSoup(html, "html.parser")
branche, umsatz = parse_infobox(soup)
# Fallback auf Kategorien
if not branche:
for category in page.categories:
if any(kw in category.lower() for kw in WHITELIST_KATEGORIEN):
branche = category
break
return page.url, branche or "k.A.", umsatz or "k.A."
except (wikipedia.exceptions.PageError,
wikipedia.exceptions.DisambiguationError,
requests.exceptions.RequestException):
for attempt in range(MAX_RETRIES):
try:
results = wikipedia.search(name, results=3)
for title in results:
try:
page = wikipedia.page(title, auto_suggest=False)
if not validate_wikipedia_content(page.content, name, domain):
continue
soup = BeautifulSoup(requests.get(page.url).text, "html.parser")
branche, umsatz = parse_infobox(soup)
except Exception as e:
print(f"⚠️ Wikipedia-Fehler ({term}, Versuch {attempt+1}): {str(e)[:100]}")
time.sleep(RETRY_DELAY)
# Fallback auf Kategorien
if not branche:
for cat in page.categories:
if any(kw in cat.lower() for kw in WHITELIST_KATEGORIEN):
branche = cat
break
return page.url, branche or "k.A.", umsatz or "k.A."
except wikipedia.exceptions.PageError:
continue
except Exception as e:
print(f"⚠️ Wikipedia-Fehler ({name}): {str(e)[:100]}")
time.sleep(RETRY_DELAY)
return "", "k.A.", "k.A."
def classify_company(row, wikipedia_url=""):
"""Verarbeitet die GPT-Klassifizierung mit Wikipedia-Integration"""
user_prompt = {
"role": "user",
"content": f"{row[0]};{row[1]};{row[2]};{row[4]};{row[5]}\nWikipedia-Link: {wikipedia_url}"
}
def query_gpt(row, wiki_url):
"""Verarbeitet die GPT-Abfrage mit verbessertem Error-Handling"""
user_content = f"{row[0]};{row[1]};{row[2]};{row[4]};{row[5]}\nWikipedia: {wiki_url}"
# GPT-Abfrage mit Retry-Logik
for attempt in range(MAX_RETRIES):
try:
response = openai.chat.completions.create(
model="gpt-3.5-turbo",
messages=[system_prompt, user_prompt],
messages=[system_prompt, {"role": "user", "content": user_content}],
temperature=0,
request_timeout=15
timeout=15
)
full_text = response.choices[0].message.content.strip()
break
return response.choices[0].message.content.strip()
except Exception as e:
print(f"⚠️ GPT-Fehler (Versuch {attempt+1}): {str(e)[:100]}")
time.sleep(RETRY_DELAY)
else:
print("❌ GPT 3x fehlgeschlagen setze auf Standardwerte")
full_text = "k.A.;k.A.;k.A.;k.A.;k.A.;k.A.;k.A.;k.A."
# Antwortverarbeitung
csv_line = next((l for l in full_text.splitlines() if ";" in l and not l.startswith("Wikipedia-Branche")), "")
parts = [v.strip().strip('"') for v in csv_line.split(";")] if csv_line else ["k.A."] * 8
parts += ["k.A."] * (8 - len(parts)) # Padding für fehlende Werte
# Logging
with open(LOG_CSV, "a", newline="", encoding="utf-8") as log:
writer = csv.writer(log, delimiter=";")
writer.writerow([datetime.now().strftime("%Y-%m-%d %H:%M:%S"), row[0], *parts, full_text])
return parts
print("❌ GPT-Abfrage fehlgeschlagen")
return "k.A.;k.A.;k.A.;k.A.;k.A.;k.A.;k.A.;k.A."
# === HAUPTPROZESS ===
for i in range(start, min(start + DURCHLÄUFE, len(sheet_values))):
# === HAUPTLOGIK ===
start_index = next((i for i, row in enumerate(sheet_values[1:], start=1) if not row[13].strip()), 1)
for i in range(start_index, min(start_index + DURCHLÄUFE, len(sheet_values))):
row = sheet_values[i]
print(f"\n[{datetime.now().strftime('%H:%M:%S')}] Verarbeite Zeile {i+1}: {row[0]}")
# Wikipedia-Datenabfrage
url, wiki_branche, umsatz = get_wikipedia_data(row[0], row[1])
# Wikipedia-Daten holen
wiki_url, wiki_branche, wiki_umsatz = get_wikipedia_data(row[0], row[1])
# GPT-Klassifizierung
gpt_data = classify_company(row, url)
(wiki_gpt, linkedin, umsatz_gpt,
new_cat, reason, fsm, techniker, techniker_reason) = gpt_data
# GPT-Abfrage
gpt_response = query_gpt(row, wiki_url)
gpt_data = [x.strip('"') for x in gpt_response.split(";")][:8]
# Priorisierung der Wikipedia-Daten
final_wiki = wiki_branche if url else "k.A."
final_umsatz = umsatz if url else "k.A."
# Finale Werte
final_branche = wiki_branche if wiki_url else "k.A."
final_umsatz = wiki_umsatz if wiki_url else "k.A."
# Daten für Google Sheet
values = [
final_wiki, # G: Wikipedia-Branche
linkedin, # H: LinkedIn-Branche
final_umsatz, # I: Umsatz
new_cat, # J: Empfohlene Neueinstufung
reason, # K: Begründung
fsm, # L: FSM-Relevanz
url, # M: Wikipedia-URL
datetime.now().strftime("%Y-%m-%d %H:%M:%S"), # N: Letzte Prüfung
techniker, # O: Techniker-Einschätzung
techniker_reason # P: Techniker-Begründung
# Google Sheet aktualisieren
update_values = [
final_branche, # G: Wikipedia-Branche
gpt_data[1], # H: LinkedIn-Branche
final_umsatz, # I: Umsatz
gpt_data[3], # J: Neueinstufung
gpt_data[4], # K: Begründung
gpt_data[5], # L: FSM-Relevanz
wiki_url, # M: Wikipedia-URL
datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
gpt_data[6], # O: Techniker-Einschätzung
gpt_data[7] # P: Techniker-Begründung
]
# Google Sheet Update
sheet.update(f"G{i+1}:P{i+1}", [values])
print(f"✅ Aktualisiert: {values[:3]}...")
sheet.update(
range_name=f"G{i+1}:P{i+1}",
values=[update_values]
)
print(f"✅ Aktualisiert: {update_values[:3]}...")
time.sleep(RETRY_DELAY)
print("\nAlle Durchläufe erfolgreich abgeschlossen")
print("\nProzess erfolgreich abgeschlossen")