diff --git a/brancheneinstufung.py b/brancheneinstufung.py index d3a5955f..677537dd 100644 --- a/brancheneinstufung.py +++ b/brancheneinstufung.py @@ -12,7 +12,7 @@ import csv # ==================== KONFIGURATION ==================== class Config: - VERSION = "1.1.11" # Neue Version mit verbesserter Umsatz- und Mitarbeiterextraktion + VERSION = "1.1.12" # Neue Version: Optimierte Umsatz- und Mitarbeiterextraktion LANG = "de" CREDENTIALS_FILE = "service_account.json" SHEET_URL = "https://docs.google.com/spreadsheets/d/1u_gHr9JUfmV1-iviRzbSe3575QEp7KLhK5jFV_gJcgo" @@ -69,6 +69,45 @@ def normalize_company_name(name): normalized = re.sub(r'\s+', ' ', normalized).strip() return normalized.lower() +def extract_numeric_value(raw_value, is_umsatz=False): + """ + Extrahiert den numerischen Wert aus raw_value. + - Bei Umsatz: Wenn "mrd" im Text vorkommt, multipliziere mit 1000; + wenn weder "mio" noch "mrd" gefunden werden, wird angenommen, dass der Wert in Euro ist, und durch 1e6 geteilt. + - Bei Mitarbeiterzahl: Entferne Tausendertrennzeichen und gib den ganzzahligen Wert zurück. + """ + raw = raw_value.lower() + match = re.search(r'([\d.,]+)', raw) + if not match: + return raw_value.strip() + num_str = match.group(1) + # Wenn Komma vorhanden, nehmen wir an, es handelt sich um einen Dezimaltrenner (mit eventuell Punkten als Tausendertrennzeichen) + if ',' in num_str: + num_str = num_str.replace('.', '').replace(',', '.') + try: + num = float(num_str) + except Exception as e: + debug_print(f"Fehler bei der Umwandlung von {num_str}: {e}") + return raw_value.strip() + else: + # Keine Kommas: Entferne alle Punkte (als Tausendertrennzeichen) + num_str = num_str.replace('.', '') + try: + num = float(num_str) + except Exception as e: + debug_print(f"Fehler bei der Umwandlung von {num_str}: {e}") + return raw_value.strip() + if is_umsatz: + if "mrd" in raw or "milliarden" in raw: + num *= 1000 + elif "mio" in raw or "millionen" in raw: + pass + else: + num /= 1e6 + return str(int(round(num))) + else: + return str(int(round(num))) + # ==================== GOOGLE SHEET HANDLER ==================== class GoogleSheetHandler: def __init__(self): @@ -176,58 +215,19 @@ class WikipediaScraper: clean_val = re.sub(r'\[.*?\]|\(.*?\)', '', raw_value) return ' '.join(clean_val.split()).strip() if target == 'umsatz': - raw = raw_value.lower() - match = re.search(r'([\d.,]+)', raw) - if match: - num_str = match.group(1) - # Falls Komma vorhanden: Punkte als Tausendertrennzeichen entfernen, Komma als Dezimaltrenner ersetzen - if ',' in num_str: - num_str = num_str.replace('.', '').replace(',', '.') - else: - num_str = num_str.replace(' ', '').replace('.', '') - try: - num = float(num_str) - except Exception as e: - debug_print(f"Umsatz-Umwandlungsfehler: {e} für {num_str}") - return raw_value.strip() - if 'mrd' in raw or 'milliarden' in raw: - num *= 1000 - elif 'mio' in raw or 'millionen' in raw: - pass - else: - num /= 1e6 - return str(int(round(num))) - return raw_value.strip() + # Extrahiere den numerischen Teil und berechne den Wert in Mio € + return extract_numeric_value(raw_value, is_umsatz=True) if target == 'mitarbeiter': - raw = raw_value.lower() - # Spezifisch nach "mitarbeiterzahl" suchen, um den direkt folgenden Zahlenwert zu extrahieren. - match = re.search(r'(?:mitarbeiterzahl|mitarbeiter)[^\d]*([\d.,\s]+)', raw) - if match: - num_str = match.group(1) - # Entferne Tausendertrennzeichen (Punkte oder Leerzeichen) - num_str = num_str.replace(" ", "") - # Falls es nur Punkte und keine Kommas gibt, behandeln wir diese als Tausendertrennzeichen. - if '.' in num_str and ',' not in num_str: - num_str = num_str.replace('.', '') - # Entferne eventuell verbleibende nicht-numerische Zeichen. - num_str = re.sub(r'[^\d]', '', num_str) - if num_str: - debug_print(f"Mitarbeiterzahl gefunden: {num_str} in Text: {raw_value}") - return num_str - # Fallback: Falls keine spezifische Suche funktioniert, versuche die erste Zahl zu extrahieren. - match = re.search(r'(\d{1,3}(?:\.\d{3})+|\d+)', raw) - if match: - num_str = match.group(1) - if '.' in num_str and ',' not in num_str: - num_str = num_str.replace('.', '') - return num_str - return raw_value.strip() + # Extrahiere den numerischen Teil; erwarte Format wie "4.175 (2021/22)" + return extract_numeric_value(raw_value, is_umsatz=False) return "k.A." + def extract_full_infobox(self, soup): infobox = soup.find('table', class_=lambda c: c and any(kw in c.lower() for kw in ['infobox', 'vcard', 'unternehmen'])) if not infobox: return "k.A." return clean_text(infobox.get_text(separator=' | ')) + def extract_fields_from_infobox_text(self, infobox_text, field_names): result = {} tokens = [token.strip() for token in infobox_text.split("|") if token.strip()] @@ -239,6 +239,7 @@ class WikipediaScraper: j += 1 result[field] = tokens[j] if j < len(tokens) else "k.A." return result + def extract_company_data(self, page_url): if not page_url: return {'url': 'k.A.', 'first_paragraph': 'k.A.', 'branche': 'k.A.', 'umsatz': 'k.A.', 'mitarbeiter': 'k.A.', 'full_infobox': 'k.A.'} @@ -262,6 +263,7 @@ class WikipediaScraper: except Exception as e: debug_print(f"Extraktionsfehler: {str(e)}") return {'url': 'k.A.', 'first_paragraph': 'k.A.', 'branche': 'k.A.', 'umsatz': 'k.A.', 'mitarbeiter': 'k.A.', 'full_infobox': 'k.A.'} + @retry_on_failure def search_company_article(self, company_name, website): search_terms = self._generate_search_terms(company_name, website) @@ -282,6 +284,63 @@ class WikipediaScraper: continue return None +# ==================== Neue Helper-Funktion für numerische Werte ==================== +def extract_numeric_value(raw_value, is_umsatz=False): + """ + Extrahiert den numerischen Wert aus raw_value. + - Falls ein Komma vorhanden ist, werden Punkte als Tausendertrennzeichen entfernt und das Komma als Dezimaltrenner genutzt. + - Falls kein Komma vorhanden ist, werden alle Punkte entfernt (als Tausendertrennzeichen). + - Für Umsatz: Wenn "mrd" im Text vorkommt, wird der Wert mit 1000 multipliziert; falls keine Einheit angegeben ist, wird angenommen, dass der Wert in Euro ist und durch 1e6 geteilt. + - Für Mitarbeiter: Der extrahierte numerische Wert wird als ganze Zahl zurückgegeben. + """ + raw = raw_value.lower() + match = re.search(r'([\d.,]+)', raw) + if not match: + return raw_value.strip() + num_str = match.group(1) + # Wenn Komma vorhanden, behandeln wir es als Dezimaltrenner + if ',' in num_str: + num_str = num_str.replace('.', '').replace(',', '.') + try: + num = float(num_str) + except Exception as e: + debug_print(f"Fehler bei der Umwandlung von {num_str}: {e}") + return raw_value.strip() + else: + # Entferne alle Punkte (als Tausendertrennzeichen) + num_str = num_str.replace('.', '') + try: + num = float(num_str) + except Exception as e: + debug_print(f"Fehler bei der Umwandlung von {num_str}: {e}") + return raw_value.strip() + if is_umsatz: + if "mrd" in raw or "milliarden" in raw: + num *= 1000 + elif "mio" in raw or "millionen" in raw: + pass + else: + num /= 1e6 + return str(int(round(num))) + else: + return str(int(round(num))) + +# ==================== GOOGLE SHEET HANDLER ==================== +class GoogleSheetHandler: + def __init__(self): + self.sheet = None + self.sheet_values = [] + self._connect() + def _connect(self): + scope = ["https://www.googleapis.com/auth/spreadsheets"] + creds = ServiceAccountCredentials.from_json_keyfile_name(Config.CREDENTIALS_FILE, scope) + self.sheet = gspread.authorize(creds).open_by_url(Config.SHEET_URL).sheet1 + self.sheet_values = self.sheet.get_all_values() + def get_start_index(self): + filled_n = [row[13] if len(row) > 13 else '' for row in self.sheet_values[1:]] + return next((i + 1 for i, v in enumerate(filled_n, start=1) if not str(v).strip()), len(filled_n) + 1) + # Update-Aufrufe erfolgen separat. + # ==================== DATA PROCESSOR ==================== class DataProcessor: def __init__(self): @@ -347,7 +406,7 @@ if __name__ == "__main__": print("Ungültige Eingabe. Bitte eine Zahl eingeben.") exit(1) else: - num_rows = None # Im Re-Evaluierungsmodus werden alle markierten Zeilen verarbeitet. + num_rows = None processor = DataProcessor() processor.process_rows(num_rows) print("\n✅ Wikipedia-Auswertung abgeschlossen")