bugfix
This commit is contained in:
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user