import os import json import time import logging import pandas as pd from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.chrome.service import Service from selenium.webdriver.chrome.options import Options as ChromeOptions from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.common.exceptions import TimeoutException, NoSuchElementException # Temporäre Konfiguration direkt im Skript class TempConfig: DEALFRONT_LOGIN_URL = "https://app.dealfront.com/login" DEALFRONT_TARGET_URL = "https://app.dealfront.com/t/prospector/companies" TARGET_SEARCH_NAME = "Facility Management" # Anzupassender Name der Suche DEALFRONT_CREDENTIALS_FILE = "/app/dealfront_credentials.json" OUTPUT_DIR = "/app/output" LOG_FORMAT = '%(asctime)s - %(levelname)-8s - %(name)-25s - %(message)s' logging.basicConfig(level=logging.INFO, format=LOG_FORMAT, force=True, handlers=[logging.StreamHandler()]) logging.getLogger("selenium").setLevel(logging.WARNING) logger = logging.getLogger(__name__) # FileHandler log_filename = f"dealfront_run_{time.strftime('%Y%m%d-%H%M%S')}.txt" log_filepath = os.path.join(OUTPUT_DIR, log_filename) try: file_handler = logging.FileHandler(log_filepath, mode='w', encoding='utf-8') file_handler.setLevel(logging.DEBUG) file_handler.setFormatter(logging.Formatter(LOG_FORMAT)) logging.getLogger().addHandler(file_handler) logger.info(f"Logging konfiguriert. Log-Datei: {log_filepath}") except Exception as e: logger.error(f"Konnte Log-Datei nicht erstellen: {e}") class DealfrontScraper: def __init__(self): logger.info("Initialisiere DealfrontScraper...") chrome_options = ChromeOptions() chrome_options.add_experimental_option("prefs", {"profile.managed_default_content_settings.images": 2}) chrome_options.add_argument("--headless") chrome_options.add_argument("--no-sandbox") chrome_options.add_argument("--disable-dev-shm-usage") chrome_options.add_argument("--window-size=1920,1080") service = Service(executable_path='/usr/bin/chromedriver') try: self.driver = webdriver.Chrome(service=service, options=chrome_options) except Exception as e: logger.critical("WebDriver konnte nicht initialisiert werden.", exc_info=True) raise self.wait = WebDriverWait(self.driver, 30) self.username, self.password = self._load_credentials() logger.info("WebDriver erfolgreich initialisiert.") def _load_credentials(self): try: with open(TempConfig.DEALFRONT_CREDENTIALS_FILE, 'r') as f: return json.load(f).get("username"), json.load(f).get("password") except Exception as e: logger.error(f"Credentials-Datei konnte nicht geladen werden: {e}") return None, None def _save_debug_artifacts(self): # Implementierung bleibt gleich pass def login(self): logger.info(f"Navigiere zur Login-Seite: {TempConfig.DEALFRONT_LOGIN_URL}") self.driver.get(TempConfig.DEALFRONT_LOGIN_URL) self.wait.until(EC.visibility_of_element_located((By.NAME, "email"))).send_keys(self.username) self.driver.find_element(By.CSS_SELECTOR, "input[type='password']").send_keys(self.password) self.driver.find_element(By.XPATH, "//button[normalize-space()='Log in']").click() logger.info("Login-Befehl gesendet. Kurze Pause...") time.sleep(5) return True def navigate_to_target(self): logger.info(f"Navigiere direkt zur Target-URL.") self.driver.get(TempConfig.DEALFRONT_TARGET_URL) self.wait.until(EC.url_contains("/t/prospector/")) logger.info(f"URL-Wechsel bestätigt.") self.wait.until(EC.visibility_of_element_located((By.XPATH, "//button[normalize-space()='+ Neue Suche']"))) logger.info("'Target'-Seite erfolgreich geladen.") return True def load_search(self, search_name): logger.info(f"Lade Suche: '{search_name}'...") search_item_selector = (By.XPATH, f"//div[contains(@class, 'truncate') and normalize-space()='{search_name}']") self.wait.until(EC.element_to_be_clickable(search_item_selector)).click() logger.info(f"Suche '{search_name}' geladen.") return True def extract_current_page_results(self): logger.warning("Extraktionsmethode ist noch nicht implementiert und wird übersprungen.") # Hier muss die robuste Warte- und Extraktionslogik implementiert werden. return [] def close(self): if self.driver: logger.info("Schließe den WebDriver.") self.driver.quit() if __name__ == "__main__": logger.info("Starte Dealfront Automatisierung - Stabiler Stand") scraper = None try: scraper = DealfrontScraper() scraper.login() scraper.navigate_to_target() scraper.load_search(TempConfig.TARGET_SEARCH_NAME) logger.info("Alle Schritte bis zur Anzeige der Ergebnisseite waren erfolgreich.") logger.info("Nächster Schritt: Implementierung der Extraktionslogik.") # Hier wird die (noch leere) Extraktionsmethode aufgerufen companies = scraper.extract_current_page_results() if companies: print("Erfolgreich extrahiert (dies sollte noch nicht passieren).") else: logger.info("Keine Daten extrahiert, wie erwartet.") except Exception as e: logger.critical(f"Ein kritischer Fehler ist aufgetreten: {e}", exc_info=True) scraper._save_debug_artifacts() finally: if scraper: logger.info("Prozess beendet. Browser bleibt 10s offen.") time.sleep(10) scraper.close()