Files
Brancheneinstufung2/brancheneinstufung.py
Floke cb298828b7 Wikipedia Bugfix
Wikipedia-Suche ist vollständig implementiert:

Suchbegriffe: vollständiger Firmenname, erste zwei Wörter, Domainname

wikipedia.search() liefert bis zu 3 Treffer

Titelvergleich verhindert falsche Zuordnung

HTML der Seite wird geladen

Infobox mit infobox oder infobox vcard wird geprüft

Branche wird aus <th>Branche</th> extrahiert

Umsatz wird aus „Umsatz“ extrahiert, falls „Mio“ enthalten, auf Zahl bereinigt (z. B. „159 Mio. €“ → 159)

 Wikipedia-Branche und Umsatz werden korrekt in wiki_branche bzw. umsatz gespeichert.

 Diese Werte werden beim Schreiben bevorzugt:

python
Copy
Edit
wiki_final = wiki_branche if wiki_branche != "k.A." else wiki
umsatz_final = umsatz if umsatz != "k.A." else umsatz_chat
 Es werden alle Spalten korrekt im Sheet geschrieben (G bis P).
2025-03-30 07:05:06 +00:00

190 lines
7.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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)
)
}
# === WIKIPEDIA DATEN LADEN ===
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 name.lower().split()[0] not in page.title.lower():
continue
url = page.url
html = requests.get(url).text
soup = BeautifulSoup(html, 'html.parser')
infobox = soup.find("table", class_=["infobox", "infobox vcard"])
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 "Branche" in th.text:
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
branche = cats[0] if cats else "k.A."
return url, branche or "k.A.", umsatz or "k.A."
except:
continue
return "", "k.A.", "k.A."
# === GPT BEWERTUNG ===
def classify_company(row):
user_prompt = {
"role": "user",
"content": f"{row[0]};{row[1]};{row[2]};{row[4]};{row[5]}"
}
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
# === 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, wiki_branche, umsatz = get_wikipedia_data(row[0], row[1])
wiki, linkedin, umsatz_chat, new_cat, reason, fsm, techniker, techniker_reason = classify_company(row)
wiki_final = wiki_branche if wiki_branche != "k.A." else wiki
umsatz_final = umsatz if umsatz != "k.A." else 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+2}:P{i+2}", values=[values])
time.sleep(5)
print("✅ Durchläufe abgeschlossen")