Code-Karte beim Zählen der Downloads ausgeschlossen

This commit is contained in:
2025-07-17 11:11:34 +00:00
parent 0eb7279740
commit c12809ed43

View File

@@ -34,13 +34,13 @@ SELECTORS = {
# Selektoren für die Statistik-Zählung
"person_all_photos": ".//div[@data-key]",
"person_purchased_photos": ".//div[@data-key and .//img[@alt='Bestellungen mit diesem Foto']]",
"person_access_card_photo": ".//div[@data-key and contains(@class, 'opacity-50')]", # NEU: Identifiziert die Zugangskarte
"potential_buyer_link": "//a[contains(@href, '/config_customers/view_customer')]",
"quick_login_url": "//a[@id='quick-login-url']",
"buyer_email": "//span[contains(., '@')]"
}
def take_error_screenshot(driver, error_name):
"""Speichert einen Screenshot des aktuellen Browserfensters in den output-Ordner."""
os.makedirs(OUTPUT_DIR, exist_ok=True)
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"error_{error_name}_{timestamp}.png"
@@ -52,7 +52,6 @@ def take_error_screenshot(driver, error_name):
print(f"!!! Konnte keinen Screenshot speichern: {e}")
def setup_driver():
"""Initialisiert und konfiguriert den Chrome WebDriver."""
print("Initialisiere Chrome WebDriver...")
options = Options()
options.add_argument('--headless')
@@ -68,7 +67,6 @@ def setup_driver():
return None
def load_all_credentials():
"""Lädt alle Anmeldedaten aus der JSON-Datei."""
try:
with open(CREDENTIALS_FILE, 'r') as f:
return json.load(f)
@@ -76,7 +74,6 @@ def load_all_credentials():
return None
def login(driver, username, password):
"""Führt den Login-Vorgang auf fotograf.de durch."""
print("Starte Login-Vorgang...")
try:
driver.get(LOGIN_URL)
@@ -102,9 +99,7 @@ def login(driver, username, password):
take_error_screenshot(driver, "login_error")
return False
# --- Modus 1: E-Mail-Listen-Erstellung ---
def process_reminder_mode(driver, job_url):
"""Sammelt Daten für die E-Mail-Erinnerungskampagne."""
wait = WebDriverWait(driver, 15)
try:
@@ -228,7 +223,6 @@ def process_reminder_mode(driver, job_url):
return final_results
def aggregate_results_by_email(results):
"""Fasst Ergebnisse pro E-Mail-Adresse zusammen."""
print("\nBeginne mit der Aggregation der Ergebnisse pro E-Mail-Adresse...")
aggregated_data = {}
for result in results:
@@ -263,7 +257,6 @@ def aggregate_results_by_email(results):
return final_list
def save_aggregated_results_to_csv(results):
"""Speichert die aggregierten Daten für Supermailer."""
if not results:
print("\nKeine Daten zum Speichern vorhanden.")
return
@@ -280,7 +273,6 @@ def save_aggregated_results_to_csv(results):
# --- Modus 2: Statistik-Auswertung ---
def process_statistics_mode(driver, job_url):
"""Sammelt und druckt Statistiken pro Album."""
wait = WebDriverWait(driver, 15)
try:
@@ -328,13 +320,17 @@ def process_statistics_mode(driver, job_url):
try:
photo_container = person_row.find_element(By.XPATH, "./following-sibling::div[1]")
# GEÄNDERTE ZÄHLLOGIK
num_total_photos = len(photo_container.find_elements(By.XPATH, SELECTORS["person_all_photos"]))
num_purchased_photos = len(photo_container.find_elements(By.XPATH, SELECTORS["person_purchased_photos"]))
num_access_cards = len(photo_container.find_elements(By.XPATH, SELECTORS["person_access_card_photo"]))
buyable_photos = num_total_photos - num_access_cards
if num_purchased_photos > 0:
children_with_purchase += 1
if num_total_photos > 0 and num_total_photos == num_purchased_photos:
if buyable_photos > 0 and buyable_photos == num_purchased_photos:
children_with_all_purchased += 1
except NoSuchElementException:
continue
@@ -356,7 +352,6 @@ def process_statistics_mode(driver, job_url):
return statistics
def save_statistics_to_csv(results):
"""Speichert die Statistik-Daten in einer CSV-Datei."""
if not results:
print("\nKeine Statistikdaten zum Speichern vorhanden.")
return
@@ -371,9 +366,7 @@ def save_statistics_to_csv(results):
writer.writerows(results)
print("Speichern erfolgreich!")
# --- Haupt-Logik ---
def get_profile_choice():
"""Zeigt ein Menü zur Profilauswahl."""
all_credentials = load_all_credentials()
if not all_credentials: return None
profiles = list(all_credentials.keys())
@@ -390,8 +383,7 @@ def get_profile_choice():
except ValueError: print("Ungültige Eingabe.")
def main():
"""Hauptfunktion des Skripts."""
print("--- Fotograf.de Scraper (v3.1 - The Analyst) ---")
print("--- Fotograf.de Scraper (v3.2 - The Master Analyst) ---")
while True:
mode = input("Bitte Modus wählen:\n 1) E-Mail-Liste erstellen\n 2) Statistik auswerten\nWahl: ")