Files
Brancheneinstufung2/dealfront_enrichment.py
2025-07-08 12:36:02 +00:00

132 lines
5.8 KiB
Python

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()