bugfix
This commit is contained in:
@@ -252,7 +252,7 @@ decorator_logger = logging.getLogger(__name__ + ".Retry")
|
||||
|
||||
|
||||
# --- Retry Decorator ---
|
||||
# KORRIGIERTE Version (Behandelt SpreadsheetNotFound und 404/400 HTTPError explizit)
|
||||
# KORRIGIERTE Version (Behandelt SpreadsheetNotFound und 404/400/401/403 HTTPError explizit)
|
||||
def retry_on_failure(func):
|
||||
"""
|
||||
Decorator, der eine Funktion bei bestimmten Fehlern mehrmals wiederholt.
|
||||
@@ -426,7 +426,7 @@ def simple_normalize_url(url):
|
||||
"""Normalisiert URL zu domain.tld oder k.A. (ohne www, ohne Pfad)."""
|
||||
if not url or not isinstance(url, str): return "k.A."
|
||||
url = url.strip()
|
||||
if not url or url.lower() == 'k.a.': return "k.A."
|
||||
if not url or url.lower() == 'k.A.': return "k.A." # Prüfe auf Kleinbuchstaben "k.A."
|
||||
# Falls kein Schema vorhanden, hinzufügen (HTTPS bevorzugen)
|
||||
if not url.lower().startswith(("http://", "https://")): url = "https://" + url
|
||||
try:
|
||||
@@ -479,7 +479,7 @@ def normalize_company_name(name):
|
||||
"""Entfernt gängige Rechtsformzusätze etc. für Vergleiche."""
|
||||
if not name: return ""
|
||||
name = clean_text(name)
|
||||
forms = [ r'gmbh', r'ges\.?\s*m\.?\s*b\.?\s*h\.?', r'gesellschaft mit beschränkter haftung', r'ug', r'u\.g\.', r'unternehmergesellschaft', r'haftungsbeschränkt', r'ag', r'a\.g\.', r'aktiengesellschaft', r'ohg', r'o\.h\.g\.', r'offene handelsgesellschaft', r'kg', r'k\.g\.', r'kommanditgesellschaft', r'gmbh\s*&\s*co\.?\s*kg', r'ges\.?\s*m\.?\s*b\.?\s*h\.?\s*&\s*co\.?\s*k\.g\.?', r'ag\s*&\s*co\.?\s*kg', r'a\.g\.?\s*&\s*co\.?\s*k\.g\.?', r'e\.k\.', r'e\.kfm\.', r'e\.kfr\.', r'eingetragene[rn]? kauffrau', r'eingetragene[rn]? kaufmann', r'ltd\.?', r'limited', r'ltd\s*&\s*co\.?\s*kg', r's\.?a\.?r\.?l\.?', r'sàrl', r'sagl', r's\.?a\.?', r'société anonyme', r'sociedad anónima', r's\.?p\.?a\.?', r'società per azioni', r'b\.?v\.?', r'besloten vennootschap', r'n\.?v\.?', r'naamloze vennootschap', r'plc\.?', r'public limited company', 'inc', 'incorporated', r'corp\.?', 'corporation', 'llc', 'limited liability company', r'kgaa', r'kommanditgesellschaft auf aktien', 'se', 'societas europaea', r'e\.?g\.?', r'eingetragene genossenschaft', 'genossenschaft', 'genmbh', r'e\.?v\.?', r'eingetragener verein', 'verein', 'stiftung', 'ggmbh', r'gemeinnützige gmbh', r'gemeinnützige[rn]? gmbh', 'gug', 'partg', 'partnerschaftsgesellschaft', 'partgmbb', 'og', r'o\.g\.', 'offene gesellschaft', r'e\.u\.', 'eingetragenes unternehmen', r'ges\.?n\.?b\.?r\.?', r'gesellschaft nach bürgerlichem recht', 'kollektivgesellschaft', 'einzelfirma', 'gruppe', 'holding', 'international', 'systeme', 'technik', 'logistik', 'solutions', 'services', 'management', 'consulting', 'produktion', 'vertrieb', 'entwicklung', 'maschinenbau', 'anlagenbau'
|
||||
forms = [ r'gmbh', r'ges\.?\s*m\.?\s*b\.?\s*h\.?', r'gesellschaft mit beschränkter haftung', r'ug', r'u\.g\.', r'unternehmergesellschaft', r'haftungsbeschränkt', r'ag', r'a\.g\.', r'aktiengesellschaft', r'ohg', r'o\.h\.g\.', r'offene handelsgesellschaft', r'kg', r'k\.g\.', r'kommanditgesellschaft', r'gmbh\s*&\s*co\.?\s*kg', r'ges\.?\s*m\.?\s*b\.?\s*h\.?\s*&\s*co\.?\s*k\.g\.?', r'ag\s*&\s*co\.?\s*kg', r'a\.g\.?\s*&\s*co\.?\s*k\.g\.?', r'e\.k\.', r'e\.kfm\.', r'e\.kfr\.', r'eingetragene[rn]? kauffrau', r'eingetragene[rn]? kaufmann', r'ltd\.?', 'limited', r'ltd\s*&\s*co\.?\s*kg', r's\.?a\.?r\.?l\.?', 'sàrl', 'sagl', r's\.?a\.?', 'société anonyme', 'sociedad anónima', r's\.?p\.?a\.?', 'società per azioni', r'b\.?v\.?', 'besloten vennootschap', r'n\.?v\.?', 'naamloze vennootschap', r'plc\.?', 'public limited company', 'inc', 'incorporated', r'corp\.?', 'corporation', 'llc', 'limited liability company', r'kgaa', r'kommanditgesellschaft auf aktien', 'se', 'societas europaea', r'e\.?g\.?', 'eingetragene genossenschaft', 'genossenschaft', 'genmbh', r'e\.?v\.?', 'eingetragener verein', 'verein', 'stiftung', 'ggmbh', r'gemeinnützige gmbh', r'gemeinnützige[rn]? gmbh', 'gug', 'partg', 'partnerschaftsgesellschaft', 'partgmbb', 'og', r'o\.g\.', 'offene gesellschaft', r'e\.u\.', 'eingetragenes unternehmen', r'ges\.?n\.?b\.?r\.?', r'gesellschaft nach bürgerlichem recht', 'kollektivgesellschaft', 'einzelfirma', 'gruppe', 'holding', 'international', 'systeme', 'technik', 'logistik', 'solutions', 'services', 'management', 'consulting', 'produktion', 'vertrieb', 'entwicklung', 'maschinenbau', 'anlagenbau'
|
||||
]
|
||||
# Pattern für ganze Wörter (case-insensitive)
|
||||
# Fügen Sie \b hinzu, um sicherzustellen, dass ganze Wörter gematcht werden (z.B. nicht "ag" in "manage")
|
||||
@@ -1545,13 +1545,14 @@ def scrape_website_details(url):
|
||||
|
||||
# --- Globale Funktion zum Scrapen des Website Rohtextes ---
|
||||
# Übernommen aus get_website_raw in Teil 7. Global platziert.
|
||||
# Nutzt globale Helfer: simple_normalize_url, clean_text, re, requests, BeautifulSoup, Config, getattr.
|
||||
@retry_on_failure
|
||||
def get_website_raw(url, max_length=20000, verify_cert=True): # Längeres Default Limit, SSL-Zertifikat standardmäßig prüfen
|
||||
"""
|
||||
Holt Textinhalt von einer Website, versucht Cookie-Banner zu umgehen.
|
||||
Gibt den Rohtext zurück oder einen Fehlerwert ("k.A.", "k.A. (Fehler)", etc.).
|
||||
"""
|
||||
if not url or not isinstance(url, str) or url.strip().lower() in ["k.a.", "kein artikel gefunden", "fehler bei suche"]:
|
||||
if not url or not isinstance(url, str) or url.strip().lower() in ["k.a.", "kein artikel gefunden", "fehler bei suche", "http:"]: # Füge "http:" hinzu basierend auf Log
|
||||
logger.debug(f"get_website_raw skipped: Ungültige oder leere URL '{url}'.")
|
||||
return "k.A."
|
||||
|
||||
@@ -4285,6 +4286,54 @@ class DataProcessor:
|
||||
all_sheet_updates = [] # Gesammelte Updates für Batch-Schreiben
|
||||
update_batch_row_limit = getattr(Config, 'UPDATE_BATCH_ROW_LIMIT', 50) # Nutze die Update-Batch-Größe aus Config
|
||||
|
||||
|
||||
# --- Worker-Funktion für Scraping (intern) ---
|
||||
# Diese Funktion wird vom ThreadPoolExecutor aufgerufen und hat Zugriff auf den umgebenden Scope.
|
||||
def scrape_raw_text_task(task_info):
|
||||
"""
|
||||
Scrapt den Rohtext einer Website in einem separaten Thread.
|
||||
Wird vom ThreadPoolExecutor in process_website_scraping_batch aufgerufen.
|
||||
Nutzt die globale Funktion get_website_raw.
|
||||
|
||||
Args:
|
||||
task_info (dict): Enthält {'row_num': int, 'url': str}.
|
||||
|
||||
Returns:
|
||||
dict: Enthält {'row_num': int, 'raw_text': str, 'error': str}.
|
||||
"""
|
||||
row_num = task_info['row_num']
|
||||
url = task_info['url']
|
||||
raw_text = "k.A."
|
||||
error = None
|
||||
|
||||
try:
|
||||
# RUFT die globale Funktion get_website_raw auf.
|
||||
# Der retry_on_failure Decorator auf get_website_raw behandelt Retries und Fehler.
|
||||
raw_text = get_website_raw(url) # <<< Hier wird die globale Funktion aufgerufen
|
||||
|
||||
# Wenn get_website_raw einen Fehler loggt und einen Fehlerstring zurückgibt,
|
||||
# wird dies im Ergebnisdict als raw_text gespeichert.
|
||||
# Wir können hier prüfen, ob der raw_text einen Fehlerwert signalisiert.
|
||||
if str(raw_text).startswith("k.A. (Fehler") or str(raw_text).startswith("FEHLER:"):
|
||||
error = f"Scraping Fehler (Details im Rohtext): {raw_text[:100]}..."
|
||||
# self.logger.error(error) # Wird bereits in get_website_raw geloggt
|
||||
pass # Fehler wurde bereits im Rückgabewert signalisiert
|
||||
|
||||
|
||||
except Exception as e:
|
||||
# Dieser Block sollte jetzt seltener erreicht werden, da get_website_raw
|
||||
# die meisten Fehler intern fängt und mit retry behandelt.
|
||||
# Wenn eine Exception hier durchkommt, ist es ein unerwarteter Fehler im Task-Handling selbst.
|
||||
error = f"Unerwarteter Fehler im Scraping Task Zeile {row_num} ({url}): {type(e).__name__} - {e}"
|
||||
# self.logger.error(error) # Loggen Sie diesen unerwarteten Fehler
|
||||
raw_text = "k.A. (Unerwarteter Fehler Task)" # Setze einen spezifischen Fehlerwert
|
||||
|
||||
|
||||
# logger.debug(f"Scraping Task Zeile {row_num} abgeschlossen. Textlänge: {len(str(raw_text))}.") # Zu viel Lärm
|
||||
return {"row_num": row_num, "raw_text": raw_text, "error": error}
|
||||
|
||||
# --- Hauptlogik: Iteriere und sammle Batches ---
|
||||
|
||||
processed_count = 0 # Zählt Zeilen, die im Batch verarbeitet (versucht) wurden
|
||||
skipped_count = 0 # Zählt Zeilen, die übersprungen wurden (wegen Inhalt oder fehlender URL)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user