Alignment Demo Update
This commit is contained in:
@@ -29,6 +29,8 @@ import csv
|
|||||||
import gender_guesser.detector as gender
|
import gender_guesser.detector as gender
|
||||||
from urllib.parse import urlparse, urlencode
|
from urllib.parse import urlparse, urlencode
|
||||||
import argparse
|
import argparse
|
||||||
|
import pandas as pd
|
||||||
|
import numpy as np # Für NaN
|
||||||
|
|
||||||
# Optional: tiktoken für Token-Zählung (Modus 8)
|
# Optional: tiktoken für Token-Zählung (Modus 8)
|
||||||
try:
|
try:
|
||||||
@@ -2190,6 +2192,9 @@ def process_contact_research(sheet_handler):
|
|||||||
debug_print("Contact Research abgeschlossen.")
|
debug_print("Contact Research abgeschlossen.")
|
||||||
|
|
||||||
# ==================== ALIGNMENT DEMO (Hauptblatt) ====================
|
# ==================== ALIGNMENT DEMO (Hauptblatt) ====================
|
||||||
|
# ==================== ALIGNMENT DEMO (Hauptblatt) ====================
|
||||||
|
# Diese Funktion ist bereits im Code vorhanden (Zeile ~1230 in der vorherigen Version)
|
||||||
|
# Sie bleibt unverändert:
|
||||||
def alignment_demo(sheet):
|
def alignment_demo(sheet):
|
||||||
"""Schreibt die Header-Struktur (Zeilen 1-5) ins angegebene Sheet."""
|
"""Schreibt die Header-Struktur (Zeilen 1-5) ins angegebene Sheet."""
|
||||||
# Definition der Header wie im Original-Code
|
# Definition der Header wie im Original-Code
|
||||||
@@ -2215,10 +2220,11 @@ def alignment_demo(sheet):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
sheet.update(values=new_headers, range_name=header_range)
|
sheet.update(values=new_headers, range_name=header_range)
|
||||||
print(f"Alignment-Demo abgeschlossen: Header in Bereich {header_range} geschrieben.")
|
print(f"Alignment-Demo abgeschlossen: Header in Bereich {header_range} geschrieben.") # Geändert zu print für Sichtbarkeit
|
||||||
|
debug_print(f"Alignment-Demo: Header in Bereich {header_range} geschrieben.")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Fehler beim Schreiben der Alignment-Demo Header: {e}")
|
print(f"FEHLER beim Schreiben der Alignment-Demo Header: {e}") # Geändert zu print
|
||||||
|
debug_print(f"FEHLER beim Schreiben der Alignment-Demo Header: {e}")
|
||||||
|
|
||||||
# ==================== DATA PROCESSOR ====================
|
# ==================== DATA PROCESSOR ====================
|
||||||
class DataProcessor:
|
class DataProcessor:
|
||||||
@@ -2502,18 +2508,16 @@ class DataProcessor:
|
|||||||
debug_print(f"Modus 22 abgeschlossen. {rows_processed} Websites ergänzt.")
|
debug_print(f"Modus 22 abgeschlossen. {rows_processed} Websites ergänzt.")
|
||||||
|
|
||||||
|
|
||||||
# ==================== MAIN FUNCTION ====================
|
|
||||||
# ==================== MAIN FUNCTION ====================
|
# ==================== MAIN FUNCTION ====================
|
||||||
def main():
|
def main():
|
||||||
# global MODE, LOG_FILE # MODE wird nicht mehr global benötigt, aber LOG_FILE schon
|
global LOG_FILE # LOG_FILE wird global benötigt
|
||||||
# -> MODE wird unten neu gesetzt, kein global nötig. LOG_FILE wird global gesetzt.
|
|
||||||
global LOG_FILE
|
|
||||||
|
|
||||||
# --- Initialisierung ---
|
# --- Initialisierung ---
|
||||||
# Argument Parser
|
# Argument Parser
|
||||||
parser = argparse.ArgumentParser(description="Firmen-Datenanreicherungs-Skript")
|
parser = argparse.ArgumentParser(description="Firmen-Datenanreicherungs-Skript")
|
||||||
parser.add_argument("--mode", type=str, help="Betriebsmodus (z.B. combined, wiki, website, branch, reeval, website_lookup, website_details, contacts, full_run)")
|
# Modus Argument
|
||||||
# HIER KORRIGIERT: --limit statt --row_limit
|
parser.add_argument("--mode", type=str, help="Betriebsmodus (z.B. combined, wiki, website, branch, reeval, website_lookup, website_details, contacts, full_run, alignment)")
|
||||||
|
# Limit Argument
|
||||||
parser.add_argument("--limit", type=int, help="Maximale Anzahl zu verarbeitender Zeilen (für Batch/sequentielle Modi)", default=None)
|
parser.add_argument("--limit", type=int, help="Maximale Anzahl zu verarbeitender Zeilen (für Batch/sequentielle Modi)", default=None)
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
@@ -2521,7 +2525,8 @@ def main():
|
|||||||
Config.load_api_keys()
|
Config.load_api_keys()
|
||||||
|
|
||||||
# Betriebsmodus ermitteln
|
# Betriebsmodus ermitteln
|
||||||
valid_modes = ["combined", "wiki", "website", "branch", "reeval", "website_lookup", "website_details", "contacts", "full_run"]
|
# HIER NEU: 'alignment' hinzugefügt
|
||||||
|
valid_modes = ["combined", "wiki", "website", "branch", "reeval", "website_lookup", "website_details", "contacts", "full_run", "alignment"]
|
||||||
mode = None
|
mode = None
|
||||||
# Priorisiere Kommandozeilenargumente
|
# Priorisiere Kommandozeilenargumente
|
||||||
if args.mode and args.mode.lower() in valid_modes:
|
if args.mode and args.mode.lower() in valid_modes:
|
||||||
@@ -2539,14 +2544,16 @@ def main():
|
|||||||
print(" website_details:Extrahiert Title/Desc/H-Tags für Zeilen mit 'x' in Spalte A")
|
print(" website_details:Extrahiert Title/Desc/H-Tags für Zeilen mit 'x' in Spalte A")
|
||||||
print(" contacts: Sucht LinkedIn Kontakte via SERP API und schreibt in 'Contacts' Blatt")
|
print(" contacts: Sucht LinkedIn Kontakte via SERP API und schreibt in 'Contacts' Blatt")
|
||||||
print(" full_run: Verarbeitet alle Zeilen sequentiell ab der ersten ohne Zeitstempel (AO)")
|
print(" full_run: Verarbeitet alle Zeilen sequentiell ab der ersten ohne Zeitstempel (AO)")
|
||||||
|
print(" alignment: Schreibt die Definitions-Header (Zeilen 1-5) ins Hauptblatt (Überschreibt A1:AS5!)") # NEUE Beschreibung
|
||||||
try:
|
try:
|
||||||
|
# HIER NEU: valid_modes für die Hilfsanzeige verwendet
|
||||||
mode_input = input(f"Geben Sie den Modus ein ({', '.join(valid_modes)}): ").strip().lower()
|
mode_input = input(f"Geben Sie den Modus ein ({', '.join(valid_modes)}): ").strip().lower()
|
||||||
if mode_input in valid_modes:
|
if mode_input in valid_modes:
|
||||||
mode = mode_input
|
mode = mode_input
|
||||||
else:
|
else:
|
||||||
print("Ungültige Eingabe. Standardmodus 'combined' wird verwendet.")
|
print("Ungültige Eingabe. Standardmodus 'combined' wird verwendet.")
|
||||||
mode = "combined" # Standardmodus
|
mode = "combined" # Standardmodus
|
||||||
# Füge eine Sicherheitsprüfung hinzu, falls input() in nohup aufgerufen wird
|
# Fehlerbehandlung für input() im Hintergrund
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
if e.errno == 9: # Bad file descriptor
|
if e.errno == 9: # Bad file descriptor
|
||||||
print("Fehler: Interaktive Modus-Abfrage nicht möglich (läuft im Hintergrund?). Standardmodus 'combined' wird verwendet.")
|
print("Fehler: Interaktive Modus-Abfrage nicht möglich (läuft im Hintergrund?). Standardmodus 'combined' wird verwendet.")
|
||||||
@@ -2555,24 +2562,21 @@ def main():
|
|||||||
print(f"Unerwarteter OS-Fehler bei Modus-Abfrage: {e}")
|
print(f"Unerwarteter OS-Fehler bei Modus-Abfrage: {e}")
|
||||||
print("Standardmodus 'combined' wird verwendet.")
|
print("Standardmodus 'combined' wird verwendet.")
|
||||||
mode = "combined"
|
mode = "combined"
|
||||||
except EOFError: # Kann auftreten, wenn stdin geschlossen ist (z.B. bei nohup)
|
except EOFError:
|
||||||
print("Fehler: Interaktive Modus-Abfrage nicht möglich (EOF). Standardmodus 'combined' wird verwendet.")
|
print("Fehler: Interaktive Modus-Abfrage nicht möglich (EOF). Standardmodus 'combined' wird verwendet.")
|
||||||
mode = "combined"
|
mode = "combined"
|
||||||
|
|
||||||
|
|
||||||
# Zeilenlimit ermitteln
|
# Zeilenlimit ermitteln (Logik bleibt unverändert, fragt nur wenn nötig)
|
||||||
row_limit = None
|
row_limit = None
|
||||||
# Priorisiere Kommandozeilenargumente
|
if args.limit is not None:
|
||||||
if args.limit is not None: # Prüfe, ob --limit explizit gesetzt wurde (auch wenn 0)
|
|
||||||
# Erlaube auch 0 als Limit (obwohl es nichts tut, ist es eine gültige Angabe)
|
|
||||||
if args.limit >= 0:
|
if args.limit >= 0:
|
||||||
row_limit = args.limit
|
row_limit = args.limit
|
||||||
print(f"Zeilenlimit (aus Kommandozeile): {row_limit}")
|
print(f"Zeilenlimit (aus Kommandozeile): {row_limit}")
|
||||||
else:
|
else:
|
||||||
print("Warnung: Negatives Zeilenlimit ignoriert. Kein Limit gesetzt.")
|
print("Warnung: Negatives Zeilenlimit ignoriert. Kein Limit gesetzt.")
|
||||||
row_limit = None
|
row_limit = None
|
||||||
# Nur wenn KEIN Limit über die Kommandozeile kam UND es ein Modus ist, der ein Limit brauchen könnte, FRAGE interaktiv
|
elif mode in ["combined", "wiki", "website", "branch", "full_run"]: # Limit nur für diese Modi relevant
|
||||||
elif mode in ["combined", "wiki", "website", "branch", "full_run"]:
|
|
||||||
try:
|
try:
|
||||||
limit_input = input("Wie viele Zeilen sollen maximal bearbeitet werden? (Enter für alle) ")
|
limit_input = input("Wie viele Zeilen sollen maximal bearbeitet werden? (Enter für alle) ")
|
||||||
if limit_input.strip():
|
if limit_input.strip():
|
||||||
@@ -2584,21 +2588,20 @@ def main():
|
|||||||
print("Warnung: Negatives Zeilenlimit ignoriert. Kein Limit gesetzt.")
|
print("Warnung: Negatives Zeilenlimit ignoriert. Kein Limit gesetzt.")
|
||||||
row_limit = None
|
row_limit = None
|
||||||
else:
|
else:
|
||||||
row_limit = None # Alle verarbeiten
|
row_limit = None
|
||||||
print("Kein Zeilenlimit gesetzt.")
|
print("Kein Zeilenlimit gesetzt.")
|
||||||
except ValueError:
|
except ValueError:
|
||||||
print("Ungültige Eingabe für Zeilenlimit. Kein Limit gesetzt.")
|
print("Ungültige Eingabe für Zeilenlimit. Kein Limit gesetzt.")
|
||||||
row_limit = None
|
row_limit = None
|
||||||
# Füge eine Sicherheitsprüfung hinzu, falls input() in nohup aufgerufen wird
|
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
if e.errno == 9: # Bad file descriptor
|
if e.errno == 9:
|
||||||
print("Warnung: Interaktive Abfrage des Limits nicht möglich (läuft im Hintergrund?). Kein Limit gesetzt.")
|
print("Warnung: Interaktive Abfrage des Limits nicht möglich (läuft im Hintergrund?). Kein Limit gesetzt.")
|
||||||
row_limit = None
|
row_limit = None
|
||||||
else:
|
else:
|
||||||
print(f"Unerwarteter OS-Fehler bei Limit-Abfrage: {e}")
|
print(f"Unerwarteter OS-Fehler bei Limit-Abfrage: {e}")
|
||||||
print("Kein Limit gesetzt.")
|
print("Kein Limit gesetzt.")
|
||||||
row_limit = None
|
row_limit = None
|
||||||
except EOFError: # Kann auftreten, wenn stdin geschlossen ist
|
except EOFError:
|
||||||
print("Warnung: Interaktive Abfrage des Limits nicht möglich (EOF). Kein Limit gesetzt.")
|
print("Warnung: Interaktive Abfrage des Limits nicht möglich (EOF). Kein Limit gesetzt.")
|
||||||
row_limit = None
|
row_limit = None
|
||||||
|
|
||||||
@@ -2608,35 +2611,39 @@ def main():
|
|||||||
debug_print(f"===== Skript gestartet =====")
|
debug_print(f"===== Skript gestartet =====")
|
||||||
debug_print(f"Version: {Config.VERSION}")
|
debug_print(f"Version: {Config.VERSION}")
|
||||||
debug_print(f"Betriebsmodus: {mode}")
|
debug_print(f"Betriebsmodus: {mode}")
|
||||||
debug_print(f"Zeilenlimit: {row_limit if row_limit is not None else 'Unbegrenzt'}")
|
# Korrigiere Logging für row_limit, wenn es 0 ist
|
||||||
|
limit_log_text = str(row_limit) if row_limit is not None else 'Unbegrenzt'
|
||||||
|
if row_limit == 0 and mode in ["combined", "wiki", "website", "branch", "full_run"]:
|
||||||
|
limit_log_text = '0 (Keine Verarbeitung geplant)'
|
||||||
|
debug_print(f"Zeilenlimit: {limit_log_text}")
|
||||||
debug_print(f"Logdatei: {LOG_FILE}")
|
debug_print(f"Logdatei: {LOG_FILE}")
|
||||||
|
|
||||||
# --- Vorbereitung ---
|
# --- Vorbereitung ---
|
||||||
# Lade Branchenschema
|
# Lade Branchenschema
|
||||||
load_target_schema() # Stellt sicher, dass globale Variablen gesetzt sind
|
load_target_schema()
|
||||||
|
|
||||||
# Initialisiere Google Sheet Handler
|
# Initialisiere Google Sheet Handler
|
||||||
try:
|
try:
|
||||||
sheet_handler = GoogleSheetHandler()
|
sheet_handler = GoogleSheetHandler()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
debug_print(f"FATAL: Konnte Google Sheet Handler nicht initialisieren: {e}")
|
debug_print(f"FATAL: Konnte Google Sheet Handler nicht initialisieren: {e}")
|
||||||
|
print(f"FEHLER: Verbindung zu Google Sheets fehlgeschlagen. Siehe Logdatei: {LOG_FILE}") # Direkte Ausgabe für den User
|
||||||
return # Abbruch
|
return # Abbruch
|
||||||
|
|
||||||
# Initialisiere DataProcessor
|
# Initialisiere DataProcessor
|
||||||
data_processor = DataProcessor(sheet_handler)
|
data_processor = DataProcessor(sheet_handler)
|
||||||
|
|
||||||
# Optional: Alignment Demo für Hauptblatt ausführen? (Bleibt auskommentiert)
|
|
||||||
# run_alignment = input("Sollen die Header im Hauptblatt aktualisiert werden (Alignment Demo)? (j/N): ").lower()
|
|
||||||
# if run_alignment == 'j':
|
|
||||||
# alignment_demo(sheet_handler.sheet)
|
|
||||||
|
|
||||||
# --- Modusausführung ---
|
# --- Modusausführung ---
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
debug_print(f"Starte Verarbeitung um {datetime.now().strftime('%H:%M:%S')}...")
|
debug_print(f"Starte Verarbeitung um {datetime.now().strftime('%H:%M:%S')}...")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if mode in ["wiki", "website", "branch", "combined"]:
|
if mode in ["wiki", "website", "branch", "combined"]:
|
||||||
run_dispatcher(mode, sheet_handler, row_limit)
|
# Stelle sicher, dass row_limit nicht 0 ist, sonst startet der Dispatcher umsonst
|
||||||
|
if row_limit == 0:
|
||||||
|
debug_print("Zeilenlimit ist 0. Überspringe Dispatcher-Aufruf.")
|
||||||
|
else:
|
||||||
|
run_dispatcher(mode, sheet_handler, row_limit)
|
||||||
elif mode == "reeval":
|
elif mode == "reeval":
|
||||||
data_processor.process_reevaluation_rows()
|
data_processor.process_reevaluation_rows()
|
||||||
elif mode == "website_lookup":
|
elif mode == "website_lookup":
|
||||||
@@ -2644,30 +2651,58 @@ def main():
|
|||||||
elif mode == "website_details":
|
elif mode == "website_details":
|
||||||
data_processor.process_website_details_for_marked_rows()
|
data_processor.process_website_details_for_marked_rows()
|
||||||
elif mode == "contacts":
|
elif mode == "contacts":
|
||||||
process_contact_research(sheet_handler) # Übergib den Handler
|
process_contact_research(sheet_handler)
|
||||||
elif mode == "full_run":
|
elif mode == "full_run":
|
||||||
start_index = sheet_handler.get_start_row_index() # Index in Datenliste (0-basiert)
|
# Behandlung von Limit 0 direkt hier
|
||||||
if start_index < len(sheet_handler.get_data()): # Nur starten, wenn Startindex valide ist
|
if row_limit == 0:
|
||||||
num_available = len(sheet_handler.get_data()) - start_index
|
debug_print("Zeilenlimit ist 0. Überspringe sequenzielle Verarbeitung.")
|
||||||
# Berechne Anzahl zu verarbeitender Zeilen basierend auf Limit
|
|
||||||
if row_limit is not None and row_limit >= 0:
|
|
||||||
num_to_process = min(row_limit, num_available)
|
|
||||||
else: # Kein Limit oder negatives Limit -> alle verfügbaren
|
|
||||||
num_to_process = num_available
|
|
||||||
|
|
||||||
if num_to_process > 0:
|
|
||||||
data_processor.process_rows_sequentially(start_index, num_to_process, process_wiki=True, process_chatgpt=True, process_website=True)
|
|
||||||
else:
|
|
||||||
debug_print("Keine Zeilen für 'full_run' zu verarbeiten (Limit 0 oder Startindex am Ende).")
|
|
||||||
else:
|
else:
|
||||||
debug_print(f"Startindex {start_index} liegt hinter der letzten Datenzeile. Keine Verarbeitung für 'full_run'.")
|
start_index = sheet_handler.get_start_row_index()
|
||||||
|
if start_index < len(sheet_handler.get_data()):
|
||||||
|
num_available = len(sheet_handler.get_data()) - start_index
|
||||||
|
if row_limit is not None and row_limit >= 0:
|
||||||
|
num_to_process = min(row_limit, num_available)
|
||||||
|
else:
|
||||||
|
num_to_process = num_available
|
||||||
|
|
||||||
|
if num_to_process > 0:
|
||||||
|
data_processor.process_rows_sequentially(start_index, num_to_process, process_wiki=True, process_chatgpt=True, process_website=True)
|
||||||
|
else:
|
||||||
|
debug_print("Keine Zeilen für 'full_run' zu verarbeiten (Limit 0 oder Startindex am Ende).")
|
||||||
|
else:
|
||||||
|
debug_print(f"Startindex {start_index} liegt hinter der letzten Datenzeile. Keine Verarbeitung für 'full_run'.")
|
||||||
|
# HIER NEU: elif für den alignment Modus
|
||||||
|
elif mode == "alignment":
|
||||||
|
print("\nACHTUNG: Dieser Modus überschreibt die Zellen A1:AS5 im Haupt-Sheet!")
|
||||||
|
print("Diese Zellen enthalten die Spaltendefinitionen (Alignment Demo).")
|
||||||
|
try:
|
||||||
|
confirm = input("Möchten Sie wirklich fortfahren? (j/N): ").strip().lower()
|
||||||
|
if confirm == 'j':
|
||||||
|
debug_print("Bestätigung erhalten. Starte Alignment Demo...")
|
||||||
|
alignment_demo(sheet_handler.sheet) # Rufe die Funktion auf
|
||||||
|
debug_print("Alignment Demo Aufruf beendet.")
|
||||||
|
else:
|
||||||
|
print("Vorgang abgebrochen.")
|
||||||
|
debug_print("Alignment Demo vom Benutzer abgebrochen.")
|
||||||
|
# Fehlerbehandlung für input() im Hintergrund
|
||||||
|
except OSError as e:
|
||||||
|
if e.errno == 9: # Bad file descriptor
|
||||||
|
print("Fehler: Interaktive Bestätigung nicht möglich (läuft im Hintergrund?). Vorgang abgebrochen.")
|
||||||
|
debug_print("Alignment Demo abgebrochen (keine interaktive Bestätigung möglich).")
|
||||||
|
else:
|
||||||
|
print(f"Unerwarteter OS-Fehler bei Bestätigung: {e}. Vorgang abgebrochen.")
|
||||||
|
debug_print(f"Alignment Demo abgebrochen (OS-Fehler: {e}).")
|
||||||
|
except EOFError:
|
||||||
|
print("Fehler: Interaktive Bestätigung nicht möglich (EOF). Vorgang abgebrochen.")
|
||||||
|
debug_print("Alignment Demo abgebrochen (EOF).")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
debug_print(f"Unbekannter Modus '{mode}' - keine Aktion ausgeführt.")
|
debug_print(f"Unbekannter Modus '{mode}' - keine Aktion ausgeführt.")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
debug_print(f"FATAL: Unerwarteter Fehler auf oberster Ebene während der Modusausführung: {e}")
|
debug_print(f"FATAL: Unerwarteter Fehler auf oberster Ebene während der Modusausführung: {e}")
|
||||||
import traceback
|
import traceback
|
||||||
debug_print(traceback.format_exc()) # Detaillierten Stacktrace loggen
|
debug_print(traceback.format_exc())
|
||||||
|
|
||||||
# --- Abschluss ---
|
# --- Abschluss ---
|
||||||
end_time = time.time()
|
end_time = time.time()
|
||||||
@@ -2680,7 +2715,7 @@ def main():
|
|||||||
try:
|
try:
|
||||||
with open(LOG_FILE, "a", encoding="utf-8") as f:
|
with open(LOG_FILE, "a", encoding="utf-8") as f:
|
||||||
f.write(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] ===== Skript wirklich beendet =====\n")
|
f.write(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] ===== Skript wirklich beendet =====\n")
|
||||||
except: pass # Ignoriere Fehler beim letzten Schreiben
|
except: pass
|
||||||
|
|
||||||
print(f"Verarbeitung abgeschlossen. Logfile: {LOG_FILE}")
|
print(f"Verarbeitung abgeschlossen. Logfile: {LOG_FILE}")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user