This commit is contained in:
2025-05-30 19:16:07 +00:00
parent a31e66ff0d
commit 16af56c0c2

View File

@@ -3638,107 +3638,139 @@ class WikipediaScraper:
return result return result
@retry_on_failure @retry_on_failure
def search_company_article(self, company_name, website=None): def search_company_article(self, company_name, website=None, max_recursion_depth=2): # max_recursion_depth hinzugefügt
""" """
Sucht einen passenden Wikipedia-Artikel fuer das Unternehmen und gibt das Sucht einen passenden Wikipedia-Artikel fuer das Unternehmen und gibt das
wikipedia.WikipediaPage Objekt zurueck, wenn ein relevanter und validierter wikipedia.WikipediaPage Objekt zurueck, wenn ein relevanter und validierter
Artikel gefunden wird. Behandelt explizit Begriffsklaerungsseiten. Artikel gefunden wird. Behandelt explizit Begriffsklaerungsseiten.
""" """
if not company_name or str(company_name).strip() == "": if not company_name or str(company_name).strip() == "":
self.logger.warning("Wikipedia search skipped: No company name provided.") # <<< GEÄNDERT self.logger.warning("Wikipedia search skipped: No company name provided.")
raise ValueError("Kein Firmenname fuer Wikipedia Suche angegeben.") raise ValueError("Kein Firmenname fuer Wikipedia Suche angegeben.")
search_terms = self._generate_search_terms(company_name, website) search_terms = self._generate_search_terms(company_name, website)
if not search_terms: if not search_terms:
self.logger.warning(f"Keine Suchbegriffe fuer '{company_name[:100]}...' generiert.") # <<< GEÄNDERT self.logger.warning(f"Keine Suchbegriffe fuer '{company_name[:100]}...' generiert.")
return None return None
self.logger.info( # <<< GEÄNDERT self.logger.info(
f"Starte Wikipedia-Suche fuer '{company_name[:100]}...' " f"Starte Wikipedia-Suche fuer '{company_name[:100]}...' "
f"(Website: {website[:100]}...) mit Begriffen: {search_terms}" f"(Website: {website[:100]}...) mit Begriffen: {search_terms}"
) )
processed_titles = set() processed_titles = set() # Verhindert Endlosschleifen bei zirkulären Redirects/Disambiguations
def check_page(title_to_check): # Innere Hilfsfunktion mit Rekursionstiefe
if title_to_check in processed_titles: def check_page_recursive(title_to_check, current_depth):
if title_to_check in processed_titles or current_depth > max_recursion_depth:
if title_to_check in processed_titles:
self.logger.debug(f" -> Titel '{title_to_check[:100]}...' bereits verarbeitet oder Rekursionstiefe überschritten.")
return None return None
processed_titles.add(title_to_check) processed_titles.add(title_to_check)
self.logger.debug(f" -> Pruefe potenziellen Artikel: '{title_to_check[:100]}...'") # <<< GEÄNDERT
self.logger.debug(f" -> Pruefe potenziellen Artikel: '{title_to_check[:100]}...' (Tiefe: {current_depth})")
try: try:
page = wikipedia.page(title_to_check, auto_suggest=False, preload=True) page = wikipedia.page(title_to_check, auto_suggest=False, preload=True)
if self._validate_article(page, company_name, website): if self._validate_article(page, company_name, website): # company_name ist der ursprüngliche Suchname
self.logger.info(f" -> Titel '{page.title[:100]}...' erfolgreich validiert!") # <<< GEÄNDERT self.logger.info(f" -> Titel '{page.title[:100]}...' erfolgreich validiert!")
return page return page
else: else:
self.logger.debug(f" -> Titel '{title_to_check[:100]}...' nicht validiert.") # <<< GEÄNDERT self.logger.debug(f" -> Titel '{title_to_check[:100]}...' nicht validiert.")
return None return None
except wikipedia.exceptions.PageError: except wikipedia.exceptions.PageError:
self.logger.debug(f" -> Seite '{title_to_check[:100]}...' nicht gefunden (PageError).") # <<< GEÄNDERT self.logger.debug(f" -> Seite '{title_to_check[:100]}...' nicht gefunden (PageError).")
return None return None
except wikipedia.exceptions.DisambiguationError as e_inner: except wikipedia.exceptions.DisambiguationError as e_inner:
self.logger.info( # <<< GEÄNDERT self.logger.info(
f" -> Begriffsklaerung '{title_to_check[:100]}...' gefunden. " f" -> Begriffsklaerung '{title_to_check[:100]}...' gefunden (Tiefe {current_depth}). "
f"Pruefe Optionen: {str(e_inner.options)[:100]}..." f"Pruefe Optionen: {str(e_inner.options)[:100]}..."
) )
if current_depth >= max_recursion_depth:
self.logger.warning(f" -> Maximale Rekursionstiefe ({max_recursion_depth}) für Begriffsklärung '{title_to_check[:100]}...' erreicht. Stoppe weitere Auflösung.")
return None
# Filtere und priorisiere Optionen
# Man könnte hier noch intelligenter filtern, z.B. Optionen bevorzugen, die "(Unternehmen)" enthalten
valid_options = []
for option in e_inner.options: for option in e_inner.options:
option_lower = option.lower() option_lower = option.lower()
if any( # Erweiterte Negativ-Filterung
if not any(
ex in option_lower ex in option_lower
for ex in ["(person)", "(ort)", "(geographie)", "liste ", "liste)"] for ex in [
): "(person)", "(familienname)", "(vorname)", "(künstlername)",
continue "(ort)", "(geographie)", "(stadt)", "(gemeinde)", "(landkreis)",
validated_option_page = check_page(option) "liste ", "liste)", "(album)", "(film)", "(lied)", "(manga)",
"(einheit)", "(maßeinheit)", "(begriffsklärung)", "Begriffsklärung)" # Begriffsklärungen explizit ausschließen für direkte Rekursion
]
) and len(option) < 100 : # Vermeide extrem lange Options-Strings
valid_options.append(option)
self.logger.debug(f" -> {len(valid_options)} potenziell relevante Optionen für '{title_to_check[:100]}...' nach Filterung: {str(valid_options)[:200]}...")
for option in valid_options:
# Rekursiver Aufruf mit erhöhter Tiefe
validated_option_page = check_page_recursive(option, current_depth + 1)
if validated_option_page: if validated_option_page:
self.logger.info( # <<< GEÄNDERT self.logger.info(
f" -> Option '{option[:100]}...' aus Begriffsklaerung erfolgreich validiert!" f" -> Option '{option[:100]}...' aus Begriffsklaerung erfolgreich validiert!"
) )
return validated_option_page return validated_option_page
self.logger.debug( # <<< GEÄNDERT
self.logger.debug(
f" -> Keine passende/validierte Unternehmens-Option in Begriffsklaerung '{title_to_check[:100]}...' gefunden." f" -> Keine passende/validierte Unternehmens-Option in Begriffsklaerung '{title_to_check[:100]}...' gefunden."
) )
return None return None # Wichtig: Gibt None zurück, wenn keine der Optionen erfolgreich war
except (requests.exceptions.RequestException, wikipedia.exceptions.WikipediaException) as e_req: except (requests.exceptions.RequestException, wikipedia.exceptions.WikipediaException) as e_req:
self.logger.warning( # <<< GEÄNDERT self.logger.warning(
f" -> Netzwerk/API-Fehler beim Laden/Validieren von '{title_to_check[:100]}...': " f" -> Netzwerk/API-Fehler beim Laden/Validieren von '{title_to_check[:100]}...': "
f"{type(e_req).__name__} - {e_req}. Ueberspringe diesen Titel." f"{type(e_req).__name__} - {e_req}. Ueberspringe diesen Titel."
) )
return None return None
except Exception as e_page: except Exception as e_page:
self.logger.error( # <<< GEÄNDERT self.logger.error(
f" -> Unerwarteter Fehler bei Verarbeitung von Titel '{title_to_check[:100]}...': " f" -> Unerwarteter Fehler bei Verarbeitung von Titel '{title_to_check[:100]}...': "
f"{type(e_page).__name__} - {e_page}" f"{type(e_page).__name__} - {e_page}"
) )
self.logger.debug(traceback.format_exc()) # <<< GEÄNDERT self.logger.debug(traceback.format_exc())
return None return None
self.logger.debug(f" -> Versuche direkten Match fuer '{company_name[:100]}...'...") # <<< GEÄNDERT # Direkter Match mit dem ursprünglichen Firmennamen
validated_page = check_page(company_name) self.logger.debug(f" -> Versuche direkten Match fuer '{company_name[:100]}...'...")
validated_page = check_page_recursive(company_name, current_depth=0) # Starte mit Tiefe 0
if validated_page: if validated_page:
return validated_page return validated_page
self.logger.debug( # <<< GEÄNDERT # Suche mit generierten Begriffen
self.logger.debug(
f" -> Kein direkter Treffer/validiert. Starte Suche mit generierten Begriffen: {search_terms}" f" -> Kein direkter Treffer/validiert. Starte Suche mit generierten Begriffen: {search_terms}"
) )
for term in search_terms: for term in search_terms:
if term == company_name: continue # Bereits oben geprüft
try: try:
self.logger.debug(f" -> Suche mit Begriff: '{term[:100]}...'...") # <<< GEÄNDERT self.logger.debug(f" -> Suche mit Begriff: '{term[:100]}...'...")
search_results = wikipedia.search(term, results=getattr(Config, 'WIKIPEDIA_SEARCH_RESULTS', 5)) search_results = wikipedia.search(term, results=getattr(Config, 'WIKIPEDIA_SEARCH_RESULTS', 3)) # Weniger Ergebnisse pro Term
self.logger.debug(f" -> Suchergebnisse fuer '{term[:100]}...': {search_results}") # <<< GEÄNDERT self.logger.debug(f" -> Suchergebnisse fuer '{term[:100]}...': {search_results}")
if not search_results: if not search_results:
self.logger.debug(f" -> Keine Suchergebnisse fuer '{term[:100]}...'.") # <<< GEÄNDERT self.logger.debug(f" -> Keine Suchergebnisse fuer '{term[:100]}...'.")
continue continue
for title in search_results: for title in search_results:
validated_page = check_page(title) validated_page = check_page_recursive(title, current_depth=0) # Starte mit Tiefe 0 für jeden neuen Suchtreffer
if validated_page: if validated_page:
return validated_page return validated_page
except Exception as e_search: except Exception as e_search:
self.logger.error( # <<< GEÄNDERT # Fehler von wikipedia.search() selbst, nicht von check_page_recursive
f"Fehler waehrend Wikipedia-Suche fuer '{term[:100]}...': " self.logger.error(
f"Fehler waehrend Wikipedia-Suche (wikipedia.search) fuer '{term[:100]}...': "
f"{type(e_search).__name__} - {e_search}" f"{type(e_search).__name__} - {e_search}"
) )
raise e_search # Hier nicht direkt 'raise e_search', da der Retry-Decorator auf search_company_article liegt.
# Wenn dies ein wiederholbarer Fehler der wikipedia-Bibliothek ist, sollte der Decorator greifen.
# Für den Moment loggen wir und machen mit dem nächsten Suchbegriff weiter.
# Bei einem persistenten API-Problem wird der äußere Decorator nach mehreren Versuchen abbrechen.
self.logger.warning( # <<< GEÄNDERT
self.logger.warning(
f"Kein passender & validierter Wikipedia-Artikel fuer '{company_name[:100]}...' gefunden nach Pruefung aller Begriffe und Optionen." f"Kein passender & validierter Wikipedia-Artikel fuer '{company_name[:100]}...' gefunden nach Pruefung aller Begriffe und Optionen."
) )
return None return None