diff --git a/brancheneinstufung.py b/brancheneinstufung.py index 2383651f..4e0e8414 100644 --- a/brancheneinstufung.py +++ b/brancheneinstufung.py @@ -1885,39 +1885,41 @@ def serp_wikipedia_lookup(company_name, website=None, min_score=0.4): # 1. Basisscore: Titelaehnlichkeit (Normalisierte Namen verwenden) similarity = SequenceMatcher(None, normalized_title, normalized_search_name).ratio() score = similarity - # logger.debug(f" -> Kandidat '{title[:100]}...': Basis-Aehnlichkeit={similarity:.2f}") # Zu viel Laerm im Debug + # logger.debug(f" -> Kandidat '{title[:100]}...': Basis-Aehnlichkeit={similarity:.2f}") + # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + # +++ KORREKTUR / HINZUFÜGUNG HIER ++++++++++++++++++++++++++++++++++++++ + # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ bonus = 0.0 # <<<<------ HIER INITIALISIEREN! - logger.debug(f" INIT BONUS: Wert von bonus direkt nach Initialisierung: {bonus} für Kandidat '{title[:50]}...'") # NEUE DEBUG-ZEILE - + logger.debug(f" INIT BONUS: Wert von bonus direkt nach Initialisierung: {bonus} für Kandidat '{title[:50]}...'") + # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + # +++ ENDE KORREKTUR / HINZUFÜGUNG ++++++++++++++++++++++++++++++++++++ + # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # NEU: Starker Bonus, wenn der normalisierte Suchname signifikant im normalisierten Titel enthalten ist # oder der normalisierte Titel im Suchnamen (für Fälle wie "Bosch (Unternehmen)" vs "Robert Bosch GmbH") - if normalized_search_name in normalized_title or normalized_title in normalized_search_name: + # Sicherstellen, dass Strings nicht leer sind, bevor 'in' verwendet wird + if normalized_search_name and normalized_title and \ + (normalized_search_name in normalized_title or normalized_title in normalized_search_name): bonus += 0.3 # Relativ starker Bonus für gute Namensübereinstimmung - # logger.debug(f" -> Bonus +0.3 fuer Namensübereinstimmung: '{normalized_search_name}' in '{normalized_title}'") + logger.debug(f" -> Bonus +0.3 fuer Namensübereinstimmung: '{normalized_search_name}' in '{normalized_title}'") # Bestehende Boni anpassen oder leicht reduzieren, wenn der obige Bonus schon greift if "(unternehmen)" in title_lower: bonus += 0.15 # Etwas reduziert, da Namensmatch wichtiger - # logger.debug(" -> Bonus +0.15 fuer '(unternehmen)'") + logger.debug(" -> Bonus +0.15 fuer '(unternehmen)'") elif re.search(r'\b(?:gmbh|ag|kg|ltd|inc|corp|s\.?a\.?|se|group|holding)\b$', title_lower): bonus += 0.05 # Kleinerer Bonus - # logger.debug(" -> Bonus +0.05 fuer Rechtsform/Gruppen-Keyword") + logger.debug(" -> Bonus +0.05 fuer Rechtsform/Gruppen-Keyword") # 3. Bonus fuer Sprache (Deutsch bevorzugt) if url.lower().startswith("https://de.wikipedia.org"): bonus += 0.05 - # logger.debug(" -> Bonus +0.05 fuer de.wikipedia.org") + logger.debug(" -> Bonus +0.05 fuer de.wikipedia.org") - - # Gesamtscore ist Basis-Aehnlichkeit plus Boni total_score = score + bonus - # logger.debug(f" -> Gesamtscore fuer '{title[:100]}...': {total_score:.3f} (Aehnlichkeit={similarity:.2f}, Bonus={bonus:.2f})") # Zu viel Laerm im Debug + logger.debug(f" -> Gesamtscore fuer '{title[:100]}...': {total_score:.3f} (Aehnlichkeit={similarity:.2f}, Bonus={bonus:.2f})") - - # Aktualisiere besten Treffer, wenn der aktuelle Kandidat einen hoeheren Score hat - # UND der Gesamtscore ueber dem definierten Mindestscore liegt. if total_score > highest_score and total_score >= min_score: highest_score = total_score best_match_url = url # Speichere die URL des besten Treffers @@ -3226,23 +3228,33 @@ class WikipediaScraper: if full_domain != "k.A.": self.logger.debug(f" -> Suche nach Domain '{full_domain}' in externen Links des Artikels...") # <<< GEÄNDERT try: - article_html = page.html() + article_html = page.html() if article_html: soup = BeautifulSoup(article_html, getattr(Config, 'HTML_PARSER', 'html.parser')) - external_links = soup.select('a[href^="http"]') + external_links = soup.select('a[href^="http"]') relevant_links = [] - for link in external_links: - href = link.get('href', '') + for link_tag in external_links: + href = link_tag.get('href', '') if href and isinstance(href, str) and full_domain in simple_normalize_url(href): if not any(ex in href.lower() for ex in ['wikipedia.org', 'wikimedia.org', 'wikidata.org', 'archive.org', 'webcitation.org']): - relevant_links.append(link) + relevant_links.append(link_tag) if relevant_links: domain_found = True + except KeyError as e_key: + if 'extlinks' in str(e_key).lower(): # Spezifisch für diesen häufigen Fehler + self.logger.warning(f"KeyError ('{e_key}') beim Zugriff auf page.html() oder Parsing für Domain-Check bei Artikel '{page.title[:100]}...'. Domain-Validierung übersprungen.") + domain_found = False + else: + self.logger.error(f"Unerwarteter KeyError bei Domain-Prüfung für '{page.title[:100]}...': {e_key}") + domain_found = False # Im Zweifel als nicht gefunden werten + # Überlegen, ob hier nicht `raise e_key` besser wäre, wenn es nicht 'extlinks' ist. except Exception as e_link_check: - self.logger.error( # <<< GEÄNDERT - f"Fehler waehrend der Domain-Link-Pruefung fuer '{page.title[:100]}...': " + self.logger.error( + f"Allgemeiner Fehler waehrend der Domain-Link-Pruefung fuer '{page.title[:100]}...': " f"{type(e_link_check).__name__} - {e_link_check}" ) + domain_found = False + # Dynamische Schwellenwert-Entscheidung is_valid = False @@ -4790,12 +4802,14 @@ class DataProcessor: num_crm_ma = get_numeric_filter_value(crm_ma_val_str, is_umsatz=False) num_wiki_ma = get_numeric_filter_value(wiki_ma_val_str, is_umsatz=False) - #self.logger.debug(f" Konsolidierung Input: CRM_U(L)='{num_crm_umsatz}', Wiki_U(W)='{num_wiki_umsatz}' (aus {source_of_wiki_data_origin}), CRM_M(M)='{num_crm_ma}', Wiki_M(X)='{num_wiki_ma}' (aus {source_of_wiki_data_origin}), Parent_D='{parent_account_name_d}'") - wiki_source_log_info = "Unbekannt/Sheet" # Default, falls Wiki-Block nicht lief + wiki_source_log_info = "Unbekannt/Sheet (Wiki-Block nicht gelaufen)" if 'source_of_wiki_data_origin_log_msg' in locals() and source_of_wiki_data_origin_log_msg: wiki_source_log_info = source_of_wiki_data_origin_log_msg - + elif 'source_of_wiki_data_origin' in locals() and source_of_wiki_data_origin: # Fallback, falls die Variable anders hieß + wiki_source_log_info = source_of_wiki_data_origin + self.logger.debug(f" Konsolidierung Input: CRM_U(L)='{num_crm_umsatz}', Wiki_U(W)='{num_wiki_umsatz}' (aus {wiki_source_log_info}), CRM_M(M)='{num_crm_ma}', Wiki_M(X)='{num_wiki_ma}' (aus {wiki_source_log_info}), Parent_D='{parent_account_name_d}'") + if parent_account_name_d and parent_account_name_d.lower() != 'k.a.': # Parent-Account (D) ist GEFÜLLT: Primär CRM-Daten der Tochter verwenden.