diff --git a/brancheneinstufung.py b/brancheneinstufung.py index 677537dd..42ce3b6f 100644 --- a/brancheneinstufung.py +++ b/brancheneinstufung.py @@ -12,7 +12,7 @@ import csv # ==================== KONFIGURATION ==================== class Config: - VERSION = "1.1.12" # Neue Version: Optimierte Umsatz- und Mitarbeiterextraktion + VERSION = "1.1.12" # Version mit optimierter Umsatz- und Mitarbeiterextraktion LANG = "de" CREDENTIALS_FILE = "service_account.json" SHEET_URL = "https://docs.google.com/spreadsheets/d/1u_gHr9JUfmV1-iviRzbSe3575QEp7KLhK5jFV_gJcgo" @@ -72,16 +72,16 @@ def normalize_company_name(name): 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. + - Wenn ein Komma vorhanden ist, werden Punkte als Tausendertrennzeichen entfernt und das Komma als Dezimaltrenner genutzt. + - Wenn kein Komma vorhanden ist, werden alle Punkte entfernt (als Tausendertrennzeichen). + - Für Umsatz: Falls "mrd" (Milliarden) vorkommt, multipliziert mit 1000; falls keine Einheit (weder "mio" noch "mrd") vorhanden ist, wird der Wert als Euro angenommen und durch 1e6 geteilt. + - Für Mitarbeiter: Der extrahierte 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, 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: @@ -90,7 +90,6 @@ def extract_numeric_value(raw_value, is_umsatz=False): 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) @@ -122,7 +121,6 @@ class GoogleSheetHandler: 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. # ==================== WIKIPEDIA SCRAPER ==================== class WikipediaScraper: @@ -215,19 +213,15 @@ class WikipediaScraper: clean_val = re.sub(r'\[.*?\]|\(.*?\)', '', raw_value) return ' '.join(clean_val.split()).strip() if target == 'umsatz': - # Extrahiere den numerischen Teil und berechne den Wert in Mio € return extract_numeric_value(raw_value, is_umsatz=True) if target == 'mitarbeiter': - # 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,30 +233,33 @@ 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.'} + return {'url': 'k.A.', 'first_paragraph': 'k.A.', 'branche': 'k.A.', + 'umsatz': 'k.A.', 'mitarbeiter': 'k.A.', 'full_infobox': 'k.A.'} try: response = requests.get(page_url) soup = BeautifulSoup(response.text, Config.HTML_PARSER) full_infobox = self.extract_full_infobox(soup) extracted_fields = self.extract_fields_from_infobox_text(full_infobox, ['Branche', 'Umsatz', 'Mitarbeiter']) - branche_val = extracted_fields.get('Branche', self._extract_infobox_value(soup, 'branche')) - umsatz_val = extracted_fields.get('Umsatz', self._extract_infobox_value(soup, 'umsatz')) - mitarbeiter_val = extracted_fields.get('Mitarbeiter', self._extract_infobox_value(soup, 'mitarbeiter')) + raw_branche = extracted_fields.get('Branche', self._extract_infobox_value(soup, 'branche')) + raw_umsatz = extracted_fields.get('Umsatz', self._extract_infobox_value(soup, 'umsatz')) + raw_mitarbeiter = extracted_fields.get('Mitarbeiter', self._extract_infobox_value(soup, 'mitarbeiter')) + umsatz_val = extract_numeric_value(raw_umsatz, is_umsatz=True) + mitarbeiter_val = extract_numeric_value(raw_mitarbeiter, is_umsatz=False) first_paragraph = self.extract_first_paragraph(page_url) return { 'url': page_url, 'first_paragraph': first_paragraph, - 'branche': branche_val, + 'branche': raw_branche, 'umsatz': umsatz_val, 'mitarbeiter': mitarbeiter_val, 'full_infobox': full_infobox } 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.'} + 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): @@ -284,63 +281,6 @@ 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): @@ -377,7 +317,8 @@ class DataProcessor: if article: company_data = self.wiki_scraper.extract_company_data(article.url) else: - company_data = {'url': 'k.A.', 'first_paragraph': 'k.A.', 'branche': 'k.A.', 'umsatz': 'k.A.', 'mitarbeiter': 'k.A.', 'full_infobox': 'k.A.'} + company_data = {'url': 'k.A.', 'first_paragraph': 'k.A.', 'branche': 'k.A.', + 'umsatz': 'k.A.', 'mitarbeiter': 'k.A.', 'full_infobox': 'k.A.'} self.sheet_handler.sheet.update(values=[[ company_data.get('url', 'k.A.'), company_data.get('first_paragraph', 'k.A.'),