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