# Neue Version mit Wikipedia-Validierung, GPT-Schutz und Antwortlogging import os import time import csv import re import pandas as pd import gspread import openai import wikipedia from bs4 import BeautifulSoup import requests from oauth2client.service_account import ServiceAccountCredentials from datetime import datetime # === KONFIGURATION === EXCEL = "Bestandsfirmen.xlsx" SHEET_URL = "https://docs.google.com/spreadsheets/d/1u_gHr9JUfmV1-iviRzbSe3575QEp7KLhK5jFV_gJcgo" CREDENTIALS = "service_account.json" LANG = "de" LOG_CSV = "gpt_antworten_log.csv" DURCHLÄUFE = int(input("Wieviele Zeilen sollen überprüft werden? ")) # === OpenAI API-KEY LADEN === with open("api_key.txt", "r") as f: openai.api_key = f.read().strip() # === GOOGLE SHEET VERBINDUNG === 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 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.set_lang(LANG) # === SYSTEM PROMPT === branches = [ "Hersteller / Produzenten > Maschinenbau", "Hersteller / Produzenten > Automobil", "Hersteller / Produzenten > Anlagenbau", "Hersteller / Produzenten > Medizintechnik", "Hersteller / Produzenten > Chemie & Pharma", "Hersteller / Produzenten > Elektrotechnik", "Hersteller / Produzenten > Lebensmittelproduktion", "Hersteller / Produzenten > IT / Telekommunikation", "Hersteller / Produzenten > Bürotechnik", "Hersteller / Produzenten > Automaten (Vending, Slot)", "Hersteller / Produzenten > Gebäudetechnik Heizung, Lüftung, Klima", "Hersteller / Produzenten > Gebäudetechnik Allgemein", "Hersteller / Produzenten > Schädlingsbekämpfung", "Hersteller / Produzenten > Fertigung", "Hersteller / Produzenten > Braune & Weiße Ware", "Versorger > Stadtwerk", "Versorger > Verteilnetzbetreiber", "Versorger > Telekommunikation", "Dienstleister > Messdienstleister", "Dienstleister > Facility Management", "Dienstleister > Healthcare/Pflegedienste", "Dienstleister > Servicedienstleister / Reparatur ohne Produktion", "Handel & Logistik > Auslieferdienste", "Handel & Logistik > Energie (Brennstoffe)", "Handel & Logistik > Großhandel", "Handel & Logistik > Einzelhandel", "Handel & Logistik > Logistik Sonstige", "Sonstige > Unternehmensberatung (old)", "Sonstige > Sonstige", "Sonstige > Agrar, Pellets (old)", "Sonstige > Sonstiger Service (old)", "Sonstige > IT Beratung", "Sonstige > Engineering", "Baubranche > Baustoffhandel", "Baubranche > Baustoffindustrie", "Baubranche > Logistiker Baustoffe", "Baubranche > Bauunternehmen", "Gutachter / Versicherungen > Versicherungsgutachten", "Gutachter / Versicherungen > Technische Gutachter", "Gutachter / Versicherungen > Medizinische Gutachten" ] 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" "Ziel-Branchenschema:\n" + "\n".join(branches) ) } # === GPT BEWERTUNG === def classify_company(row, wikipedia_url=""): user_prompt = { "role": "user", "content": ( f"{row[0]};{row[1]};{row[2]};{row[4]};{row[5]}\n" f"Wikipedia-Link: {wikipedia_url}" ) } response = openai.chat.completions.create( model="gpt-3.5-turbo", messages=[system_prompt, user_prompt], temperature=0 ) full_text = response.choices[0].message.content.strip() lines = full_text.splitlines() csv_line = next((l for l in lines if ";" in l and not l.lower().startswith("wikipedia-branche")), "") parts = [v.strip().strip('"') for v in csv_line.split(";")] if csv_line else [] if len(parts) != 8: print("⚠️ Antwort unvollständig → Setze alles auf 'k.A.'") parts = ["k.A."] * 8 with open(LOG_CSV, "a", newline="", encoding="utf-8") as log: writer = csv.writer(log, delimiter=";") writer.writerow([row[0], *parts, full_text]) return parts # === WIKIPEDIA DATEN LADEN === # Positivliste für Wikipedia-Kategorien, die auf Unternehmen hinweisen können WHITELIST_KATEGORIEN = [ "Unternehmen", "Hersteller", "Produktion", "Industrie", "Maschinenbau", "Technik", "Dienstleistungsunternehmen" ] def get_wikipedia_data(name, website_hint=""): begriffe = [name.strip(), " ".join(name.split()[:2])] if website_hint: parts = website_hint.replace("https://", "").replace("http://", "").split(".") if len(parts) > 1: begriffe.append(parts[0]) for suchbegriff in begriffe: results = wikipedia.search(suchbegriff, results=3) for title in results: try: page = wikipedia.page(title) if any(x in page.title.lower() for x in ["krankenkasse", "versicherung"]): continue url = page.url html = requests.get(url).text if website_hint: domain_fragment = website_hint.lower().split(".")[0] if domain_fragment not in html.lower(): continue if name.lower().split()[0] not in page.title.lower(): continue soup = BeautifulSoup(html, 'html.parser') infobox = soup.find("table", class_=["infobox", "infobox vcard"]) if not infobox: tables = soup.find_all("table") for table in tables: if any("Branche" in (th.text if th else '') for th in table.find_all("th")): infobox = table break branche = umsatz = "" if infobox: for row in infobox.find_all("tr"): th, td = row.find("th"), row.find("td") if not th or not td: continue if th and "branche" in th.text.lower().strip(): branche = td.text.strip() if "Umsatz" in th.text: umsatz_raw = td.text.strip() if "Mio" in umsatz_raw: match = re.search(r"(\d+[,.]?\d*)", umsatz_raw) if match: umsatz = match.group(1).replace(",", ".") if not branche: cats = page.categories if any(any(w.lower() in c.lower() for w in WHITELIST_KATEGORIEN) for c in cats): branche = cats[0] else: return "", "k.A.", "k.A." return url, branche or "k.A.", umsatz or "k.A." except: continue return "", "k.A.", "k.A." # === VERARBEITUNG === for i in range(start, min(start + DURCHLÄUFE, len(sheet_values))): row = sheet_values[i] print(f"[{time.strftime('%H:%M:%S')}] Verarbeite Zeile {i+1}: {row[0]}") url, _, _ = get_wikipedia_data(row[0], row[1]) wiki, linkedin, umsatz_chat, new_cat, reason, fsm, techniker, techniker_reason = classify_company(row, wikipedia_url=url) wiki_final = wiki umsatz_final = umsatz_chat values = [ wiki_final, linkedin, umsatz_final, new_cat, reason, fsm, url, datetime.now().strftime("%Y-%m-%d %H:%M:%S"), techniker, techniker_reason ] sheet.update(range_name=f"G{i+1}:P{i+1}", values=[values]) time.sleep(5) print("✅ Durchläufe abgeschlossen")