- Beschreibt die Hauptfunktion und den Zweck des Moduls. - Dokumentiert die wichtigsten öffentlichen Methoden.
Projekt: Automatisierte Unternehmensbewertung & Lead-Generierung v2.2.1
1. Projektübersicht
Dieses Repository enthält eine Suite von Python-Skripten zur automatisierten Anreicherung und Analyse von Unternehmensdaten. Das System ist modular aufgebaut und für den Betrieb in einem Docker-Container ausgelegt.
brancheneinstufung.py: Das Kernmodul zur Datenanreicherung (Web, Wikipedia, KI-Analyse).duplicate_checker.py: Ein Modul zur intelligenten Duplikatsprüfung.generate_marketing_text.py: Eine Engine zur Erstellung personalisierter Marketing-Texte.app.py& Docker: Eine fernsteuerbare Schnittstelle via Google Sheets.
2. Aktueller Status: KRITISCHER FEHLER (BLOCKER)
Das gesamte System ist derzeit nicht lauffähig. Ein Inkompatibilitätsproblem zwischen dem bestehenden Code und der installierten Version der openai-Python-Bibliothek führt zu einem ModuleNotFoundError bei jedem Versuch, eine KI-Funktion aufzurufen. Dies verhindert jegliche Weiterentwicklung und Nutzung.
3. Nächster Schritt
Priorität 1: Behebung des openai-Abhängigkeitskonflikts. Die gewählte Strategie ist ein gezieltes Downgrade der openai-Bibliothek auf eine mit dem Code kompatible Version, um die Funktionalität schnellstmöglich wiederherzustellen.
planning.md (v2.2.1)
code
Markdown
Projektplanung v2.2.1
1. Aktueller Stand
- [X] Architektur & Module: Alle Kernmodule sind konzipiert und implementiert.
- [!] System-Blocker: Ein Versionskonflikt der
openai-Bibliothek legt das gesamte System lahm. Alle Funktionen, die auf die KI zugreifen, stürzen mit einemModuleNotFoundErrorab.
2. Strategischer Plan
Phase 1: Stabilität wiederherstellen (Hotfix)
- [ ] Schritt 1.1 (Analyse): Überprüfung aller Code-Stellen, die
openai-Fehlerklassen importieren oder verwenden, um den Umfang des Problems zu bestätigen. - [ ] Schritt 1.2 (Downgrade): Modifikation der
requirements.txt, um dieopenai-Bibliothek auf eine stabile, kompatible Version (z.B.0.28.0) festzuschreiben. - [ ] Schritt 1.3 (Anwendung): Neubau des Docker-Images (
docker build), um die Installation der korrekten Bibliotheksversion zu erzwingen. - [ ] Schritt 1.4 (Validierung): Durchführung eines Testlaufs (z.B.
reclassify_branches), um zu bestätigen, dass derModuleNotFoundErrorbehoben ist und die KI-Aufrufe wieder funktionieren.
Phase 2: Geplante Weiterentwicklung (nach Hotfix)
- [ ] Finalisierung des Duplikats-Checks.
- [ ] Vervollständigung der Wissensbasis und Generierung aller Marketing-Texte.
- [ ] (Zukünftig) Planung des Code-Refactorings, um die neue
openaiv1.x API zu unterstützen.
Automatisierte Unternehmensbewertung & Lead-Generierung
Version: 2.1.0 (nach Implementierung des Sync-Moduls)
Projektbeschreibung
Dieses Projekt automatisiert die Anreicherung von Unternehmensdaten aus einem D365-CRM-System. Es nutzt externe APIs (Google, Wikipedia, OpenAI) und Web-Scraping, um Stammdaten zu validieren, zu ergänzen und neue, marketing-relevante Informationen (z.B. FSM-Pitches) zu generieren. Die Verarbeitung und Speicherung der angereicherten Daten erfolgt in einem Google Sheet.
Aktueller Status (August 2025)
- Systemstabilität: Das System ist nach der Behebung von Inkompatibilitäten mit der OpenAI-Bibliothek stabil und voll lauffähig.
- Daten-Import: Ein robuster, intelligenter Synchronisations-Mechanismus (
sync_manager.py) wurde implementiert. Er gleicht einen vollständigen D365-Excel-Export mit dem Google Sheet ab, aktualisiert Stammdaten nach definierten Fachregeln und markiert Datätze für die Neu-Anreicherung. - Kernfunktionen: Datenanreicherung (Wikipedia, Website-Scraping) und KI-basierte Analysen (Brancheneinstufung, Text-Zusammenfassungen) sind operational.
- Nächster Schritt: Implementierung des Daten-Exports aus dem Google Sheet zur Aktualisierung des D365-Systems.
Duplicate Checker (duplicate_checker_old.py)
Hauptfunktion
Das Skript duplicate_checker_old.py (Version 2.15) ist ein spezialisiertes Werkzeug zur Identifizierung von potenziellen Duplikaten zwischen zwei Unternehmenslisten in Google Sheets: einer Matching-Liste (Matching_Accounts) und einer Referenz-CRM-Liste (CRM_Accounts). Es verwendet einen gewichteten, heuristischen Algorithmus, um für jeden Eintrag in der Matching-Liste den wahrscheinlichsten Treffer im CRM-Bestand zu finden und bewertet diesen mit einem numerischen Score.
Abhängigkeiten
pandas: Zur Datenmanipulation und -analyse.thefuzz: Für Fuzzy-String-Vergleiche zur Bewertung der Namensähnlichkeit.gspread,oauth2client: Für die Interaktion mit der Google Sheets API.- Lokale Module:
helpers.py: Stellt Normalisierungsfunktionen (normalize_company_name,simple_normalize_url) und eine optionale Web-Suche (serp_website_lookup) bereit.config.py: Zentralisiert Konfigurationswerte und API-Schlüssel.google_sheet_handler.py: Kapselt die Logik für den Zugriff auf Google Sheets.
Konfiguration
Die Logik des Skripts wird durch mehrere Konstanten am Anfang der Datei gesteuert:
- Sheet-Namen:
CRM_SHEET_NAMEundMATCHING_SHEET_NAME. - Score-Schwellenwerte:
SCORE_THRESHOLD(Standard: 80) undSCORE_THRESHOLD_WEAK(95), ein strengerer Wert für Treffer ohne starke Indikatoren wie Domain- oder Standortübereinstimmung. - Penalties:
CITY_MISMATCH_PENALTY(30) undCOUNTRY_MISMATCH_PENALTY(40) werden vom Score abgezogen, wenn Standorte voneinander abweichen. - Prefiltering:
PREFILTER_MIN_PARTIAL(70) undPREFILTER_LIMIT(30) zur Vorauswahl potenzieller Kandidaten, um die Performance zu verbessern. - Stop-Wörter:
STOP_TOKENS_BASEundCITY_TOKENS(dynamisch generiert) enthalten Begriffe, die bei Namensvergleichen ignoriert werden, um die Signalqualität zu erhöhen.
Ablauf-Logik
- Initialisierung: Das Skript richtet das Logging ein, lädt API-Schlüssel (optional für SerpAPI) und initialisiert den
GoogleSheetHandler. - Daten laden: Die Daten aus den beiden Google Sheets (
CRM_AccountsundMatching_Accounts) werden in Pandas DataFrames geladen. - SerpAPI-Fallback (Optional): Für Einträge in der Matching-Liste ohne Website wird versucht, über die SerpAPI eine URL zu finden. Das Vertrauen in die gefundene URL wird bewertet (
hoch,mittel,niedrig). - Normalisierung: Unternehmensnamen, Domains, Orte und Länder in beiden DataFrames werden standardisiert (z.B. Kleinschreibung, Entfernung von Rechtsformzusätzen).
- Index-Erstellung: Zur Optimierung der Suche werden mehrere "Blocking"-Indizes aus den CRM-Daten erstellt:
- Ein
domain_indexfür schnelle Suchen über die Website-Domain. - Ein
token_indexfür die Suche nach einzelnen Namensbestandteilen. - Eine
token_freqZählung, um seltene und damit aussagekräftige Namensbestandteile zu identifizieren.
- Ein
- Iteratives Matching: Das Skript durchläuft jeden Datensatz der Matching-Liste:
a. Kandidatenauswahl: Anstatt jeden Eintrag mit der gesamten CRM-Liste zu vergleichen, wird eine kleine, relevante Untergruppe von Kandidaten ausgewählt. Die Auswahl erfolgt priorisiert: zuerst über Domain-Übereinstimmung, dann über den seltensten Namens-Token und zuletzt über einen allgemeinen Prefilter.
b. Scoring: Jeder Kandidat wird mit dem aktuellen Matching-Datensatz verglichen. Die Funktion
calculate_similarityberechnet einen Score basierend auf einer gewichteten Formel, die Namensähnlichkeit, Domain-Match, Standortübereinstimmung, Boni und Strafen berücksichtigt. c. Bester Treffer: Der Kandidat mit dem höchsten Score wird als potenzielles Duplikat ausgewählt. - Ergebnis-Aggregation: Die Ergebnisse (bester Treffer, Score, Begründung der Bewertung) werden gesammelt.
- Daten zurückschreiben: Die Matching-Liste wird um die Ergebnisspalten (
Match,Score,Match_Grund) erweitert und vollständig in das Google SheetMatching_Accountszurückgeschrieben. Ein lokales CSV-Backup wird ebenfalls erstellt.
brancheneinstufung2.py
Hauptfunktion
Das Skript brancheneinstufung2.py ist der zentrale Einstiegspunkt und Orchestrator für die Datenanreicherungs-Pipeline. Es dient nicht der direkten Implementierung der Verarbeitungslogik, sondern dem Parsen von Kommandozeilen-Argumenten, der Initialisierung von Handler-Klassen (GoogleSheetHandler, WikipediaScraper, DataProcessor, SyncManager) und dem Starten des vom Benutzer ausgewählten Verarbeitungsmodus. Das Skript ist hochgradig modular und delegiert die eigentliche Arbeit an die DataProcessor-Klasse.
Abhängigkeiten
- Standardbibliotheken:
logging,os,argparse,time,datetime. - Lokale Module:
config.py: Stellt globale Konfigurationsparameter und die Projektversion bereit.helpers.py: Bietet Hilfsfunktionen, z.B. für das Erstellen von Log-Dateinamen und das Initialisieren des Branchenschemas.google_sheet_handler.py: Kapselt die gesamte Kommunikation mit der Google Sheets API.wikipedia_scraper.py: Stellt Methoden zum Suchen und Parsen von Wikipedia-Artikeln bereit.data_processor.py: Enthält die Kernlogik für alle Datenverarbeitungsschritte.sync_manager.py: Implementiert die Logik zum Abgleich von CRM-Exporten mit dem Google Sheet.
Wichtige Funktionen/Methoden
Die Logik des Skripts ist primär in der main()-Funktion enthalten und lässt sich in folgende Schritte unterteilen:
- Argumenten-Parsing: Mittels
argparsewird die Kommandozeile ausgewertet. Der wichtigste Parameter ist--mode, der den auszuführenden Prozess festlegt (z.B.sync,full_run,reeval,predict_technicians). Weitere Parameter wie--limitoder--start_sheet_rowerlauben eine feingranulare Steuerung der zu verarbeitenden Datenmenge. - Interaktiver Modus: Wird kein
--modeübergeben, startet ein interaktiver Modus, in dem der Benutzer aus einer Liste aller verfügbaren Modi auswählen kann. - Initialisierung: Basierend auf dem gewählten Modus werden die notwendigen Klassen instanziiert. Für die meisten Anreicherungs-Modi wird ein
DataProcessor-Objekt erstellt, das wiederum Instanzen desGoogleSheetHandlerundWikipediaScrapererhält. Für densync-Modus wird derSyncManagerverwendet. - Modus-Dispatching: Eine
if/elif/else-Struktur leitet die Ausführung an die passende Methode weiter.sync/simulate_sync: Ruft denSyncManagerauf, um einen D365-Excel-Export mit dem Google Sheet abzugleichen.full_run: Startet einen sequentiellen Anreicherungsprozess für Zeilen, die noch nicht verarbeitet wurden.reeval: Verarbeitet Zeilen, die explizit für eine Neubewertung markiert wurden.reclassify_branches: Führt eine Neubewertung der Branchenzuordnung für alle oder eine Teilmenge der Zeilen durch.train_technician_model/predict_technicians: Steuert das Training und die Anwendung eines Machine-Learning-Modells zur Vorhersage von Techniker-Anzahlen.- Dynamische Aufrufe: Viele Modi (z.B.
wiki_verify,website_scraping) werden dynamisch aufgerufen, indem Methoden desDataProcessor-Objekts ausgeführt werden, deren Namen dem Modus entsprechen (z.B.process_wiki_verify).
- Fehlerbehandlung und Logging: Das gesamte Skript ist von einem
try...except...finally-Block umschlossen, der Fehler abfängt, protokolliert und sicherstellt, dass das Logging am Ende sauber beendet wird.
Kernlogik (data_processor.py)
Die Klasse DataProcessor ist das Herzstück der Anreicherungslogik und enthält alle Methoden zur schrittweisen Verarbeitung von Unternehmensdaten.
setup()
- Zweck: Initialisiert den
DataProcessor, indem das Ziel-Branchenschema geladen und das trainierte Machine-Learning-Modell für die Technikerschätzung in den Speicher geladen wird. - Input: Keine direkten Argumente, greift aber auf die Konfigurationsdateien (
ziel_Branchenschema.csv,technician_decision_tree_model.pkletc.) zu. - Output: Gibt
Truebei Erfolg zurück und setzt das interne Flagis_setup_complete. Bei Fehlern wirdFalsezurückgegeben und das Skript beendet.
process_rows_sequentially(...)
- Zweck: Führt den vollständigen, schrittweisen Anreicherungsprozess für einen definierten Bereich von Zeilen im Google Sheet aus. Dies ist der Hauptmodus für die initiale Verarbeitung neuer Daten.
- Input:
start_sheet_row(Startzeile),num_to_process(Anzahl der Zeilen), sowie boolesche Flags (process_wiki_steps,process_chatgpt_steps, etc.) zur Steuerung der auszuführenden Anreicherungsschritte. - Output: Die Methode hat keinen direkten Rückgabewert, aber ihr Seiteneffekt ist die Aktualisierung der verarbeiteten Zeilen im Google Sheet mit den angereicherten Daten.
process_reevaluation_rows(...)
- Zweck: Führt den vollständigen Anreicherungsprozess gezielt für Zeilen aus, die im Google Sheet manuell mit einem 'x' in der "ReEval Flag"-Spalte markiert wurden. Vor der Neubewertung werden alle zuvor abgeleiteten Daten in der Zeile gelöscht.
- Input:
row_limit(maximale Anzahl zu verarbeitender Zeilen),clear_flag(ob das 'x'-Flag nach der Verarbeitung entfernt werden soll) und die booleschen Flags zur Schritt-Steuerung. - Output: Aktualisiert die markierten Zeilen im Google Sheet mit neu angereicherten Daten.
process_website_scraping(...)
- Zweck: Führt einen Batch-Prozess ausschließlich für das Scrapen von Websites durch. Die Methode identifiziert Zeilen, in denen der "Website Scrape Timestamp" fehlt, und extrahiert parallel den Rohtext und die Meta-Details der jeweiligen Unternehmens-Websites.
- Input:
start_sheet_row,end_sheet_row,limitzur Eingrenzung des Verarbeitungsbereichs. - Output: Schreibt den extrahierten Rohtext, Meta-Details, einen Status zur URL-Prüfung und einen Zeitstempel in die entsprechenden Spalten im Google Sheet.
process_summarize_website(...)
- Zweck: Führt einen Batch-Prozess zur Zusammenfassung von bereits extrahierten Website-Rohtexten mittels KI durch.
- Input:
start_sheet_row,end_sheet_row,limit. Die Methode verarbeitet Zeilen, bei denen der Rohtext vorhanden, aber die Zusammenfassung noch leer ist. - Output: Schreibt die KI-generierte Zusammenfassung in die Spalte "Website Zusammenfassung" im Google Sheet.
process_branch_batch(...) / reclassify_all_branches(...)
- Zweck: Führt eine (Neu-)Bewertung der Branchenzugehörigkeit für einen Zeilenbereich im Batch-Verfahren durch. Die Methode sammelt relevante Informationen (CRM-Daten, Website-Zusammenfassung, Wikipedia-Inhalte) und sendet sie gebündelt an die KI, um eine effiziente und konsistente Brancheneinstufung zu erhalten.
- Input:
start_sheet_row,end_sheet_row,limit. - Output: Aktualisiert die Spalten zur KI-basierten Brancheneinstufung ("Chat Vorschlag Branche", Konfidenz, Begründung etc.) im Google Sheet.
process_wiki_verify(...)
- Zweck: Verifiziert in einem Batch-Prozess, ob der in einer Zeile hinterlegte Wikipedia-Artikel thematisch zum Unternehmen passt. Nutzt KI, um die Konsistenz zu prüfen und ggf. einen passenderen Artikel vorzuschlagen.
- Input:
start_sheet_row,end_sheet_row,limit. Verarbeitet Zeilen, die eine Wiki-URL, aber noch keinen Verifizierungs-Timestamp haben. - Output: Schreibt das Ergebnis der KI-Prüfung (OK, X), eine Begründung und ggf. einen Alternativvorschlag in die entsprechenden Spalten im Google Sheet.
process_find_wiki_serp(...)
- Zweck: Sucht für große Unternehmen (definiert über Mindestumsatz/-mitarbeiter), bei denen noch keine Wikipedia-URL bekannt ist, über eine Google-Suche (SerpAPI) nach einem passenden Wikipedia-Artikel.
- Input:
start_sheet_row,end_sheet_row,limit,min_employees,min_umsatz. - Output: Wenn eine passende URL gefunden wird, wird diese in die "Wiki URL"-Spalte eingetragen und die Zeile für eine Neubewertung (
ReEval Flag) markiert.
process_contact_search(...)
- Zweck: Führt eine Suche nach LinkedIn-Kontakten für bestimmte Positionen (z.B. Serviceleiter, IT-Leiter) bei den Unternehmen im Sheet durch.
- Input:
start_sheet_row,end_sheet_row,limit. Verarbeitet Zeilen, die noch keinen "Contact Search Timestamp" haben. - Output: Schreibt die Anzahl der gefundenen Kontakte pro Kategorie in die "Linked... gefunden"-Spalten und speichert detaillierte Kontaktinformationen in einem separaten "Contacts"-Tabellenblatt.
train_technician_model()
- Zweck: Bereitet die vorhandenen Daten auf, trainiert ein Machine-Learning-Modell (RandomForest) zur Vorhersage von Servicetechniker-Anzahlen, führt ein Hyperparameter-Tuning durch und speichert das trainierte Modell sowie den zugehörigen Imputer als
.pkl-Dateien. - Input: Keine direkten Argumente. Die Methode liest die Trainingsdaten aus dem konfigurierten Google Sheet.
- Output: Erstellt und speichert die
technician_decision_tree_model.pkl- undmedian_imputer.pkl-Dateien sowie eine JSON-Datei mit den verwendeten Features.
process_predict_technicians(...)
- Zweck: Wendet das trainierte ML-Modell auf Zeilen an, für die noch keine Techniker-Schätzung vorliegt, aber die notwendigen Input-Features (Umsatz, Mitarbeiter, Branche) vorhanden sind.
- Input:
start_sheet_row,end_sheet_row,limit. - Output: Schreibt den vorhergesagten Techniker-Bucket (z.B. "Techniker_Klein (0-49)") in die Spalte "Geschaetzter Techniker Bucket".
Hilfsfunktionen (helpers.py)
Diese Datei enthält eine Sammlung von globalen, wiederverwendbaren Hilfsfunktionen, die in verschiedenen Modulen des Projekts verwendet werden.
Decorators
retry_on_failure(func)
- Zweck: Ein Decorator, der eine Funktion bei bestimmten, temporären Fehlern (z.B. Netzwerkprobleme, API-Rate-Limits) automatisch mehrmals ausführt. Er verwendet eine exponentielle Backoff-Strategie, um die Wartezeit zwischen den Versuchen zu erhöhen.
- Input: Eine Funktion, die dekoriert werden soll.
- Output: Das Ergebnis der dekorierten Funktion oder löst eine Ausnahme aus, wenn alle Wiederholungsversuche fehlschlagen.
Logging & Token Counting
token_count(text, model=None)
- Zweck: Zählt die Anzahl der Tokens in einem gegebenen Text. Verwendet die
tiktoken-Bibliothek für eine genaue Zählung, falls verfügbar, andernfalls schätzt sie die Anzahl basierend auf Leerzeichen. - Input:
text(der zu analysierende String),model(optional, das zu verwendende KI-Modell). - Output: Eine Ganzzahl, die die Anzahl der Tokens darstellt.
create_log_filename(mode)
- Zweck: Erstellt einen standardisierten, zeitgestempelten Dateinamen für Log-Dateien.
- Input:
mode(ein String, der den aktuellen Ausführungsmodus beschreibt, z.B. 'full_run'). - Output: Ein String, der den vollständigen Pfad zur Log-Datei enthält (z.B.
Log/2025-11-07_10-30_v221_Modus-full_run.txt).
Text-, String- & URL-Utilities
simple_normalize_url(url)
- Zweck: Bereinigt und normalisiert eine URL auf ihre Kern-Domain (z.B.
https://www.beispiel.de/path->beispiel.de). - Input:
url(ein String mit einer URL). - Output: Ein normalisierter Domain-String oder "k.A." bei ungültiger Eingabe.
normalize_string(s)
- Zweck: Standardisiert einen String, indem Umlaute (ä -> ae) und gängige Sonderzeichen ersetzt werden.
- Input:
s(ein beliebiger String). - Output: Der normalisierte String.
clean_text(text)
- Zweck: Bereinigt einen Text von unerwünschten Artefakten, die typischerweise beim Scrapen von Websites oder Wikipedia auftreten (z.B.
[1],[Bearbeiten], überflüssige Leerzeichen). - Input:
text(ein String). - Output: Der bereinigte Text.
normalize_company_name(name)
- Zweck: Normalisiert einen Firmennamen, indem gängige Rechtsformzusätze (GmbH, AG, etc.) und andere generische Begriffe entfernt werden, um Vergleiche zu erleichtern.
- Input:
name(ein Firmenname als String). - Output: Der normalisierte Firmenname in Kleinbuchstaben.
extract_numeric_value(raw_value, is_umsatz=False)
- Zweck: Extrahiert und normalisiert einen numerischen Wert aus einem unstrukturierten String. Kann Einheiten wie "Mio.", "Mrd." oder "Tsd." interpretieren und in einen Basiswert umrechnen.
- Input:
raw_value(ein String, z.B. "ca. 250 Mio. EUR"),is_umsatz(ein Flag, das die Umrechnung für Umsätze steuert, z.B. Rückgabe in Millionen). - Output: Ein String mit der normalisierten Zahl (z.B. "250") oder "k.A.".
API Wrappers & Externe Dienste
call_openai_chat(...)
- Zweck: Eine zentrale Wrapper-Funktion für Aufrufe an die OpenAI Chat-API. Kapselt die Authentifizierung, die Fehlerbehandlung und den eigentlichen API-Aufruf.
- Input:
prompt(der an die KI gesendete Text),temperature(steuert die Kreativität der Antwort),model(das zu verwendende KI-Modell). - Output: Der von der KI generierte Antwort-Text als String.
summarize_website_content(raw_text, company_name)
- Zweck: Nutzt die KI, um den Rohtext einer Website zu analysieren und eine strukturierte Zusammenfassung des Geschäftsmodells und des Potenzials für Field Service Management (FSM) zu erstellen.
- Input:
raw_text(der Inhalt der Website),company_name(Name des Unternehmens). - Output: Ein formatierter String, der das Geschäftsmodell, das FSM-Potenzial und Belegsätze enthält.
evaluate_branche_chatgpt(...)
- Zweck: Führt eine KI-basierte Brancheneinstufung für ein einzelnes Unternehmen durch. Sendet ein Unternehmensprofil und ein vordefiniertes Branchenschema an die KI.
- Input:
company_name,website_summary,wiki_absatz. - Output: Ein Dictionary mit der vorgeschlagenen "Branche", "Konfidenz" und "Begruendung".
evaluate_branches_batch(companies_data)
- Zweck: Führt die Brancheneinstufung für eine Liste von Unternehmen in einem einzigen API-Aufruf durch, um die Effizienz zu steigern.
- Input:
companies_data(eine Liste von Dictionaries, die Unternehmensprofile enthalten). - Output: Eine Liste von Dictionaries mit den Ergebnissen für jedes Unternehmen.
generate_fsm_pitch(...)
- Zweck: Generiert einen hochpersonalisierten, einleitenden Satz für eine Marketing-E-Mail (FSM-Pitch), basierend auf den gesammelten Unternehmensdaten.
- Input: Diverse Unternehmensdaten wie Name, Branche, Zusammenfassungen und Mitarbeiter-/Technikerzahlen.
- Output: Ein einzelner, prägnanter Satz als String.
serp_website_lookup(company_name)
- Zweck: Verwendet die SerpAPI (Google-Suche), um die offizielle Website eines Unternehmens zu finden. Filtert dabei unzuverlässige Quellen wie soziale Medien oder Nachrichtenportale heraus.
- Input:
company_name. - Output: Die normalisierte URL der gefundenen Website oder "k.A.".
search_linkedin_contacts(...)
- Zweck: Führt eine gezielte Google-Suche über die SerpAPI durch, um LinkedIn-Profile von Mitarbeitern in bestimmten Positionen (z.B. "Serviceleiter") bei einem Unternehmen zu finden.
- Input:
company_name,website,position_query(z.B. "Leiter Kundendienst"),crm_kurzform. - Output: Eine Liste von Dictionaries, die die gefundenen Kontakte mit Namen, Position und LinkedIn-URL enthalten.
Website Scraping & Validierung
get_website_raw(url, ...)
- Zweck: Lädt den reinen Textinhalt von einer Webseite. Die Funktion ist gehärtet, um mit verschiedenen Fehlern (SSL, Timeout, Connection Errors) umzugehen und versucht, Cookie-Banner intelligent zu entfernen.
- Input:
url(die zu scrapende URL). - Output: Der extrahierte Text der Website als String oder ein Fehlerhinweis (z.B. "k.A. (Timeout)").
is_valid_wikipedia_article_url(url)
- Zweck: Überprüft, ob eine gegebene URL tatsächlich auf einen existierenden Wikipedia-Artikel verweist und nicht auf eine "Seite existiert nicht"-Seite.
- Input:
url(die zu prüfende Wikipedia-URL). - Output:
True, wenn der Artikel existiert, andernfallsFalse.
google_sheet_handler.py
Hauptfunktion
Das Modul google_sheet_handler.py dient als zentraler Wrapper für sämtliche Interaktionen mit dem Google Sheet, das als primärer Datenspeicher für das Projekt fungiert. Es abstrahiert die Komplexität der gspread API und stellt eine robuste, wiederverwendbare Schnittstelle für Lese- und Schreibvorgänge bereit. Die Klasse GoogleSheetHandler kapselt die Verbindungslogik, die Authentifizierung über Service-Accounts und bietet Methoden für spezifische Datenmanipulationen.
Methodenbeschreibung
-
__init__(self, sheet_url=None): Der Konstruktor initialisiert den Handler. Er übernimmt optional einesheet_url. Wenn keine URL angegeben wird, greift er auf den Wert aus derconfig.pyzurück. -
load_data(self): Stellt die Verbindung zum Google Sheet her (falls noch nicht geschehen) und lädt den gesamten Inhalt des Haupt-Arbeitsblatts in den internen Speicher der Klasse. Diese Methode ist mit einem Retry-Decorator versehen, um bei temporären Netzwerkproblemen robust zu sein. -
get_sheet_as_dataframe(self, sheet_name): Liest ein spezifisches Arbeitsblatt (übersheet_nameidentifiziert) aus dem Google Sheet und gibt dessen Inhalt als Pandas DataFrame zurück. Dies ist nützlich für datenanalytische Aufgaben. -
append_rows(self, sheet_name, values): Fügt eine oder mehrere neue Zeilen am Ende eines bestimmten Arbeitsblatts an.valuesist dabei eine Liste von Listen (jede innere Liste repräsentiert eine Zeile). -
clear_and_write_data(self, sheet_name, data): Löscht den gesamten Inhalt eines Arbeitsblatts und schreibt anschließend neue Daten hinein. Dies ist nützlich, um ein Sheet vollständig zu synchronisieren. -
batch_update_cells(self, update_data): Führt eine Stapelverarbeitung von Zell-Updates durch. Diese Methode ist wesentlich performanter als einzelne Zell-Updates, da sie mehrere Änderungen in einer einzigen API-Anfrage bündelt. -
get_main_sheet_name(self): Gibt den Namen des Haupt-Arbeitsblatts (typischerweise 'Tabelle1') zurück.
wikipedia_scraper.py
Hauptfunktion
Das Modul wikipedia_scraper.py kapselt alle Interaktionen mit Wikipedia. Seine Hauptaufgabe ist es, für ein gegebenes Unternehmen den relevantesten Wikipedia-Artikel zu finden, diesen zu validieren und anschließend strukturierte Daten wie den Unternehmenssitz, die Branche, den Umsatz und die Mitarbeiterzahl aus dem Artikel zu extrahieren. Es verwendet eine "Google-First"-Strategie, bei der die SerpAPI zur Identifizierung des wahrscheinlichsten Artikels genutzt wird, bevor eine detaillierte, faktenbasierte Validierung erfolgt.
Methodenbeschreibung
-
__init__(self, user_agent=None): Initialisiert den Scraper, setzt die Sprache für diewikipedia-Bibliothek (typischerweise 'de') und konfiguriert einerequests.Sessionmit einem benutzerdefinierten User-Agent für HTTP-Anfragen. -
serp_wikipedia_lookup(self, company_name, lang='de'): Nutzt die SerpAPI, um eine Google-Suche nach dem offiziellen Wikipedia-Artikel eines Unternehmens durchzuführen. Dies ist der erste und wichtigste Schritt, um einen Kandidaten-Artikel zu finden. -
search_company_article(self, company_name, ...): Orchestriert den gesamten Such- und Validierungsprozess. Ruft zuerstserp_wikipedia_lookupauf, um eine URL zu erhalten. Anschließend wird der gefundene Artikel geladen und mit der internen Methode_validate_articleauf Relevanz geprüft. -
_validate_article(self, page, company_name, ...): Führt eine faktenbasierte Überprüfung eines Wikipedia-Artikels durch. Anstatt sich nur auf den Titel zu verlassen, prüft die Methode harte Kriterien wie die Übereinstimmung der Website-Domain (aus den Weblinks des Artikels) oder des Unternehmenssitzes (aus der Infobox). -
extract_company_data(self, url_or_page): Die zentrale Extraktionsmethode. Nimmt eine URL oder einwikipedia.page-Objekt entgegen und extrahiert daraus strukturierte Daten. Sie parst die Infobox des Artikels, um Werte für Branche, Umsatz, Mitarbeiter und Sitz zu finden, und extrahiert zusätzlich den Einleitungstext sowie die Kategorien. -
_extract_infobox_value(self, soup, target): Eine interne Hilfsmethode, die gezielt nach Schlüsselwörtern (z.B. "Branche", "Umsatz") in der Infobox eines Artikels sucht und den zugehörigen Wert extrahiert und normalisiert. -
_parse_sitz_string_detailed(self, raw_sitz_string_input): Eine spezialisierte Hilfsmethode, die versucht, aus dem oft unstrukturierten Textfeld für den Unternehmenssitz die Stadt und das Land zu trennen und zu normalisieren.
knowledge_base_builder.py
Hauptfunktion
Das Modul knowledge_base_builder.py ist dafür verantwortlich, eine Wissensbasis für die automatische Zuordnung von Jobtiteln zu Abteilungen zu erstellen. Es verarbeitet eine Liste von Jobtiteln und deren zugehörigen Abteilungen und Branchen aus einem Google Sheet. Das Skript generiert zwei Haupt-Artefakte:
- Exaktes Mapping (
exact_match_map.json): Eine einfache Zuordnung von exakten, normalisierten Jobtiteln zu ihrer dominantesten Abteilung. - Keyword-Regeln (
keyword_rules.json): Eine Sammlung von Regeln, die Schlüsselwörter pro Abteilung identifiziert und optional branchenspezifische Anforderungen für die Zuordnung hinzufügen, basierend auf der Häufigkeit von Branchen innerhalb der Abteilung.
Das Ziel ist es, die automatische und präzise Klassifizierung neuer, unbekannter Jobtitel zu ermöglichen.
Methodenbeschreibung
-
setup_logging(): Eine Hilfsfunktion, die das Logging für das Skript konfiguriert und sicherstellt, dass alle Ausgaben sowohl in eine Datei als auch in die Konsole geschrieben werden. -
build_knowledge_base(): Dies ist die Hauptfunktion des Moduls, die den gesamten Prozess der Wissensbasiserstellung orchestriert:- Daten laden: Stellt eine Verbindung zum konfigurierten Google Sheet (definiert in
SOURCE_SHEET_NAME) her und lädt die Daten in einen Pandas DataFrame. - Datenbereinigung: Entfernt Zeilen mit fehlenden oder leeren Jobtiteln/Abteilungen und normalisiert die Jobtitel für konsistente Vergleiche.
- Exaktes Mapping: Gruppiert die Jobtitel nach ihrer normalisierten Form und ermittelt die am häufigsten (modal) vorkommende Abteilung, um eine direkte 1:1-Zuordnung zu erstellen. Das Ergebnis wird als JSON-Datei (
exact_match_map.json) gespeichert. - Keyword-Regeln erstellen: Für jede Abteilung werden die häufigsten und aussagekräftigsten Schlüsselwörter aus den zugehörigen Jobtiteln extrahiert. Dabei werden eine vordefinierte Liste von Stoppwörtern und generischen Begriffen ignoriert. Diese Regeln erhalten eine Priorität basierend auf
DEPARTMENT_PRIORITIES. - Branchenspezifische Anpassung: Optional wird geprüft, ob eine Abteilung stark mit einer bestimmten Branchengruppe (definiert in
BRANCH_GROUP_RULES) korreliert. Wenn eine hohe Spezifität (>BRANCH_SPECIFICITY_THRESHOLD) und genügend Datenpunkte vorhanden sind, wird diese Branchenanforderung zur Keyword-Regel hinzugefügt. Das Ergebnis wird als JSON-Datei (keyword_rules.json) gespeichert. - Fehlerbehandlung: Robuste Fehlerbehandlung für Datei-I/O und Datenladen aus Google Sheets.
- Daten laden: Stellt eine Verbindung zum konfigurierten Google Sheet (definiert in
contact_grouping.py
Hauptfunktion
Das Modul contact_grouping.py ist für die automatische Klassifizierung von Jobtiteln in vordefinierte Abteilungen zuständig. Es nutzt eine mehrstufige Logik, die auf einer Kombination aus regelbasierten Mappings (exakte Treffer und Keyword-Regeln) und einer KI-gestützten Klassifizierung basiert. Das Ziel ist es, die Jobtitel von Kontakten aus einem Google Sheet (Matching_Positions) einer passenden Abteilung zuzuordnen, wobei auch der Unternehmensbranche-Kontext berücksichtigt wird.
Methodenbeschreibung
-
__init__(self): Initialisiert dieContactGrouper-Klasse und bereitet die internen Variablen für die Wissensbasis vor. -
load_knowledge_base(self): Lädt die zuvor erstellten Wissensbasis-Dateien (exact_match_map.jsonundkeyword_rules.json) in den Speicher. Diese Dateien enthalten die Regeln für die regelbasierte Zuordnung. Außerdem generiert es Beispiele für den KI-Prompt aus der geladenen Wissensbasis. -
_load_json(self, file_path): Eine interne Hilfsmethode zum sicheren Laden und Parsen von JSON-Dateien. -
_normalize_text(self, text): Eine interne Hilfsmethode zur Normalisierung von Texten (Kleinschreibung, Leerzeichen entfernen). -
_generate_ai_examples(self): Generiert einen Teil des KI-Prompts, der Beispiele für typische Jobtitel pro Abteilung enthält. Dies hilft der KI, die Klassifizierungsaufgabe besser zu verstehen. -
_find_best_match(self, job_title, company_branch): Die Kernlogik für die regelbasierte Zuordnung. Sie versucht zuerst einen exakten Match desjob_titlezu finden. Wenn dies fehlschlägt, werden Keyword-Regeln angewendet, wobei diecompany_branchzur Verfeinerung der Zuordnung genutzt wird. Prioritäten der Abteilungen werden bei mehreren Treffern berücksichtigt. -
_get_ai_classification(self, contacts_to_classify): Sendet eine Liste von Jobtiteln, die nicht regelbasiert zugeordnet werden konnten, an die OpenAI API zur KI-gestützten Klassifizierung. Der Prompt enthält die gültigen Abteilungen und generierte Beispiele, um die KI-Antwort zu steuern. Die Ergebnisse werden als Dictionary zurückgegeben. -
_append_learnings_to_source(self, gsh, new_mappings_df): Hängt neue, von der KI erfolgreich klassifizierte Jobtitel und deren Abteilungen an das Quell-Sheet (CRM_Jobtitles) an, um die Wissensbasis kontinuierlich zu erweitern. -
process_contacts(self): Die Hauptmethode, die den gesamten Kontakt-Klassifizierungsprozess steuert:- Lädt die Kontaktdaten aus dem
TARGET_SHEET_NAMEGoogle Sheet. - Führt die regelbasierte Zuordnung (
_find_best_match) für alle Jobtitel durch. - Identifiziert Jobtitel, die nicht regelbasiert zugeordnet werden konnten (
DEFAULT_DEPARTMENT). - Sendet diese unklassifizierten Jobtitel in Batches an die KI (
_get_ai_classification) zur weiteren Klassifizierung. - Aktualisiert die
Department-Spalte im DataFrame mit den KI-Ergebnissen. - Hängt neue KI-Erkenntnisse an das Lern-Quell-Sheet an (
_append_learnings_to_source). - Schreibt die finalen, klassifizierten Daten zurück in das
TARGET_SHEET_NAMEGoogle Sheet.
- Lädt die Kontaktdaten aus dem