From 79c01b15505a558d7bbd72ce2366638923f5da4b Mon Sep 17 00:00:00 2001 From: Floke Date: Mon, 14 Jul 2025 07:12:21 +0000 Subject: [PATCH] mehr wartezeit Letzte Version liefert immer nur Duplikate. --- dealfront_enrichment.py | 72 +++++++++++++++++++---------------------- 1 file changed, 34 insertions(+), 38 deletions(-) diff --git a/dealfront_enrichment.py b/dealfront_enrichment.py index 60359da9..6a661d26 100644 --- a/dealfront_enrichment.py +++ b/dealfront_enrichment.py @@ -81,7 +81,6 @@ class DealfrontScraper: self.driver.find_element(By.XPATH, "//button[normalize-space()='Log in']").click() logger.info("Login-Befehl gesendet. Warte 5 Sekunden auf Session-Etablierung.") time.sleep(5) - # Verifizierung, dass wir nicht mehr auf der Login-Seite sind if "login" not in self.driver.current_url: logger.info("Login erfolgreich, URL hat sich geändert.") return True @@ -108,25 +107,6 @@ class DealfrontScraper: except Exception as e: logger.warning(f"Fehler beim langsamen Scrollen: {e}") - def wait_for_table_content_change(self, previous_first_cell_text, timeout=20): - """ - Wartet, bis sich der Text der ersten Zelle der Tabelle geändert hat. - """ - start_time = time.time() - while time.time() - start_time < timeout: - try: - first_cell = self.driver.find_element(By.CSS_SELECTOR, "table#t-result-table tbody tr:first-child td") - current_text = first_cell.text.strip() - if current_text and current_text != previous_first_cell_text: - logger.info(f"Text der ersten Zelle hat sich geändert: '{previous_first_cell_text}' -> '{current_text}'") - return True - except Exception: - pass - time.sleep(0.5) - logger.warning("Timeout beim Warten auf Änderung des Inhalts der ersten Tabellenzelle.") - return False - - def navigate_and_load_search(self, search_name): try: logger.info(f"Navigiere direkt zur Target-Seite und lade die Suche...") @@ -144,12 +124,11 @@ class DealfrontScraper: self._save_debug_artifacts("navigation_or_search_load") return False - def extract_current_page_results(self): + def extract_current_page_results(self, page_number=None): results = [] rows_selector = (By.XPATH, "//table[@id='t-result-table']/tbody/tr[.//a[contains(@class, 't-highlight-text')]]") - try: - data_rows = self.driver.find_elements(*rows_selector) + data_rows = [row for row in self.driver.find_elements(*rows_selector) if row.is_displayed()] for row in data_rows: try: name = row.find_element(By.CSS_SELECTOR, ".sticky-column a.t-highlight-text").get_attribute("title").strip() @@ -158,17 +137,22 @@ class DealfrontScraper: website = row.find_element(By.CSS_SELECTOR, "a.text-gray-400.t-highlight-text").text.strip() except NoSuchElementException: pass - results.append({'name': name, 'website': website}) + res = {'name': name, 'website': website} + if page_number is not None: + res['page'] = page_number + results.append(res) except NoSuchElementException: continue except Exception as e: logger.error(f"Fehler bei der Extraktion auf der aktuellen Seite: {e}") - return results def scrape_all_pages(self, max_pages=10): + """ + Iteriert durch alle Ergebnisseiten, wartet nach jedem Paginieren explizit auf neue Seitenzahl, + wartet nach jedem Seitenwechsel und Scrollen ausreichend, und sammelt alle Firmenzeilen seitengetreu. + """ all_companies = [] - previous_first_cell_text = "" for page_number in range(1, max_pages + 1): logger.info(f"--- Verarbeite Seite {page_number} ---") try: @@ -180,22 +164,22 @@ class DealfrontScraper: logger.info("Warte 5 Sekunden, um sicherzugehen, dass alle Daten geladen sind...") time.sleep(5) - # Vor Pagination: Text der ersten Zelle merken + # Vor Pagination: Aktive Seitenzahl merken try: - first_cell = self.driver.find_element(By.CSS_SELECTOR, "table#t-result-table tbody tr:first-child td") - previous_first_cell_text = first_cell.text.strip() - logger.info(f"Text der ersten Zelle vor Pagination: '{previous_first_cell_text}'") - except Exception: - previous_first_cell_text = "" - logger.warning("Konnte Text der ersten Zelle vor Pagination nicht ermitteln.") + active_page_elem = self.driver.find_element(By.CSS_SELECTOR, "a.eb-pagination-button.active") + active_page_num = active_page_elem.text.strip() + logger.info(f"Vor Pagination: Aktive Seite: {active_page_num}") + except NoSuchElementException: + active_page_num = None + logger.warning("Vor Pagination: Konnte aktive Seite nicht ermitteln.") self.scroll_table_slowly() logger.info("Warte nach Scrollen nochmals 3 Sekunden...") time.sleep(3) # Jetzt erst Daten extrahieren - page_results = self.extract_current_page_results() - logger.info(f"Seite {page_number}: {len(page_results)} Firmen gefunden. Gesamt bisher: {len(all_companies) + len(page_results)}") + page_results = self.extract_current_page_results(page_number=page_number) + logger.info(f"Seite {page_number}: {len(page_results)} Firmen gefunden. Erste Firmen: {[r['name'] for r in page_results[:3]]}") all_companies.extend(page_results) # Pagination-Buttons loggen und Weiter-Button suchen @@ -237,8 +221,18 @@ class DealfrontScraper: self.driver.execute_script("arguments[0].click();", next_button) logger.info("Klick auf Weiter-Button ausgeführt.") - # Warte auf Änderung des Inhalts der ersten Tabellenzelle - self.wait_for_table_content_change(previous_first_cell_text, timeout=30) + # Warte auf neue aktive Seitenzahl + def page_changed(driver): + try: + elem = driver.find_element(By.CSS_SELECTOR, "a.eb-pagination-button.active") + page_num = elem.text.strip() + logger.debug(f"Nach Pagination: Aktive Seite: {page_num}") + return page_num != active_page_num + except Exception: + return False + + self.wait.until(page_changed) + logger.info("Seitenwechsel erfolgreich verifiziert (aktive Seitenzahl hat sich geändert).") except Exception as e: logger.error(f"Fehler beim Klicken auf den Weiter-Button oder beim Warten auf neue Seite: {e}") @@ -269,6 +263,8 @@ if __name__ == "__main__": if all_companies: df = pd.DataFrame(all_companies) + # Optional: Deduplizieren nach Name, Website und Seite + # df = df.drop_duplicates(subset=["name", "website", "page"]) output_csv_path = os.path.join(Config.OUTPUT_DIR, f"dealfront_results_{time.strftime('%Y%m%d-%H%M%S')}.csv") df.to_csv(output_csv_path, index=False, sep=';', encoding='utf-8-sig') logger.info(f"Ergebnisse ({len(df)} Firmen) erfolgreich in '{output_csv_path}' gespeichert.") @@ -280,4 +276,4 @@ if __name__ == "__main__": finally: if scraper: scraper.close() - logger.info("Dealfront Automatisierung beendet.") \ No newline at end of file + logger.info("Dealfront Automatisierung beendet.")