Facebook - Workflow geht aber Popup nicht da mit Browser nicht anbtouchen
Dieser Commit ist enthalten in:
@ -168,7 +168,11 @@ class FacebookRegistration:
|
||||
logger.info(f"Navigiere zu {self.automation.base_url}")
|
||||
|
||||
# Navigiere zur Facebook-Seite
|
||||
self.automation.browser.navigate_to(self.automation.base_url)
|
||||
navigation_success = self.automation.browser.navigate_to(self.automation.base_url)
|
||||
|
||||
if not navigation_success:
|
||||
logger.error(f"Navigation zu {self.automation.base_url} fehlgeschlagen")
|
||||
return False
|
||||
|
||||
# Warte auf Seitenladung
|
||||
self.automation.human_behavior.wait_for_page_load(multiplier=1.5)
|
||||
@ -178,11 +182,20 @@ class FacebookRegistration:
|
||||
|
||||
# Prüfe ob wir auf Facebook sind
|
||||
current_url = self.automation.browser.page.url
|
||||
logger.info(f"Aktuelle URL nach Navigation: {current_url}")
|
||||
|
||||
# Debug: Prüfe sichtbare Elemente
|
||||
logger.debug(f"Sichtbare Buttons: {self.automation.browser.page.locator('button').count()}")
|
||||
logger.debug(f"Sichtbare Links: {self.automation.browser.page.locator('a').count()}")
|
||||
|
||||
if "facebook.com" in current_url:
|
||||
logger.info("Erfolgreich zu Facebook navigiert")
|
||||
return True
|
||||
else:
|
||||
logger.error(f"Nicht auf Facebook gelandet: {current_url}")
|
||||
# Zusätzliche Debug-Info
|
||||
page_title = self.automation.browser.page.title()
|
||||
logger.debug(f"Seiten-Titel: {page_title}")
|
||||
return False
|
||||
|
||||
except Exception as e:
|
||||
@ -287,15 +300,31 @@ class FacebookRegistration:
|
||||
button_clicked = True
|
||||
|
||||
if button_clicked:
|
||||
# Warte auf Formular-Ladung
|
||||
self.automation.human_behavior.wait_for_page_load()
|
||||
self.automation._take_screenshot("registration_form")
|
||||
# Warte auf Formular-Ladung mit längerer Wartezeit
|
||||
self.automation.human_behavior.wait_for_page_load(multiplier=2.0)
|
||||
|
||||
# Extra Wartezeit für Facebook's React-Rendering
|
||||
self.automation.human_behavior.random_delay(2.0, 3.0)
|
||||
|
||||
# Prüfe ob Browser noch aktiv ist
|
||||
if not self.automation.browser or not self.automation.browser.page:
|
||||
logger.error("Browser wurde unerwartet geschlossen")
|
||||
return False
|
||||
|
||||
try:
|
||||
self.automation._take_screenshot("registration_form")
|
||||
except Exception as e:
|
||||
logger.warning(f"Screenshot fehlgeschlagen: {e}")
|
||||
|
||||
# Prüfe ob wir auf der Registrierungsseite sind
|
||||
current_url = self.automation.browser.page.url
|
||||
if "/r.php" in current_url or "registration" in current_url:
|
||||
logger.info("Registrierungsformular erfolgreich geöffnet")
|
||||
return True
|
||||
try:
|
||||
current_url = self.automation.browser.page.url
|
||||
if "/r.php" in current_url or "registration" in current_url:
|
||||
logger.info("Registrierungsformular erfolgreich geöffnet")
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.error(f"Fehler beim Abrufen der URL: {e}")
|
||||
return False
|
||||
|
||||
logger.error("Konnte Registrierungsformular nicht öffnen")
|
||||
return False
|
||||
@ -307,6 +336,7 @@ class FacebookRegistration:
|
||||
def _fill_registration_form(self, account_data: Dict[str, Any]) -> bool:
|
||||
"""
|
||||
Füllt das Registrierungsformular aus.
|
||||
Verbesserte Version mit Fallback-Selektoren und robusterem Handling.
|
||||
|
||||
Args:
|
||||
account_data: Account-Daten
|
||||
@ -317,90 +347,234 @@ class FacebookRegistration:
|
||||
try:
|
||||
logger.info("Fülle Registrierungsformular aus")
|
||||
|
||||
# Vorname
|
||||
if not self.automation.ui_helper.type_text_human_like(
|
||||
self.selectors.REG_FIRSTNAME_FIELD,
|
||||
account_data["first_name"]
|
||||
):
|
||||
logger.error("Fehler beim Eingeben des Vornamens")
|
||||
# Prüfe ob Browser noch aktiv ist
|
||||
if not self.automation.browser or not self.automation.browser.page:
|
||||
logger.error("Browser ist nicht mehr aktiv vor Formular-Ausfüllung")
|
||||
return False
|
||||
|
||||
# Nachname
|
||||
if not self.automation.ui_helper.type_text_human_like(
|
||||
# Debug: Prüfe welche Input-Felder sichtbar sind
|
||||
try:
|
||||
visible_inputs = self.automation.browser.page.locator("input[type='text']").count()
|
||||
logger.debug(f"Anzahl sichtbarer Text-Input-Felder: {visible_inputs}")
|
||||
|
||||
# Liste alle sichtbaren Inputs mit Namen auf
|
||||
all_inputs = self.automation.browser.page.locator("input").all()
|
||||
for idx, inp in enumerate(all_inputs[:10]): # Nur erste 10 zur Sicherheit
|
||||
try:
|
||||
name = inp.get_attribute("name")
|
||||
placeholder = inp.get_attribute("placeholder")
|
||||
aria_label = inp.get_attribute("aria-label")
|
||||
logger.debug(f"Input {idx}: name='{name}', placeholder='{placeholder}', aria-label='{aria_label}'")
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
logger.warning(f"Debug-Ausgabe fehlgeschlagen: {e}")
|
||||
|
||||
# Vorname mit Fallback
|
||||
firstname_selectors = [
|
||||
self.selectors.REG_FIRSTNAME_FIELD,
|
||||
self.selectors.REG_FIRSTNAME_FIELD_ALT,
|
||||
"input[placeholder*='Vorname']",
|
||||
"input[name='firstname']", # Direkter Name-Selektor
|
||||
"input[aria-label*='Vorname' i]" # Case-insensitive aria-label
|
||||
]
|
||||
firstname_filled = False
|
||||
for selector in firstname_selectors:
|
||||
logger.debug(f"Versuche Vorname-Selektor: {selector}")
|
||||
try:
|
||||
if self.automation.browser.is_element_visible(selector, timeout=1000):
|
||||
logger.debug(f"Selektor {selector} ist sichtbar")
|
||||
if self.automation.ui_helper.type_text_human_like(selector, account_data["first_name"]):
|
||||
logger.info(f"Vorname eingegeben mit: {selector}")
|
||||
firstname_filled = True
|
||||
break
|
||||
else:
|
||||
logger.debug(f"Selektor {selector} nicht sichtbar")
|
||||
except Exception as e:
|
||||
logger.debug(f"Fehler bei Selektor {selector}: {e}")
|
||||
|
||||
if not firstname_filled:
|
||||
logger.error(f"Fehler beim Eingeben des Vornamens. Getestete Selektoren: {firstname_selectors}")
|
||||
# Zusätzliche Debug-Info
|
||||
try:
|
||||
current_url = self.automation.browser.page.url
|
||||
logger.error(f"Aktuelle URL beim Fehler: {current_url}")
|
||||
except:
|
||||
pass
|
||||
return False
|
||||
|
||||
# Nachname mit Fallback
|
||||
lastname_selectors = [
|
||||
self.selectors.REG_LASTNAME_FIELD,
|
||||
account_data["last_name"]
|
||||
):
|
||||
self.selectors.REG_LASTNAME_FIELD_ALT,
|
||||
"input[placeholder*='Nachname']"
|
||||
]
|
||||
lastname_filled = False
|
||||
for selector in lastname_selectors:
|
||||
if self.automation.browser.is_element_visible(selector, timeout=1000):
|
||||
if self.automation.ui_helper.type_text_human_like(selector, account_data["last_name"]):
|
||||
logger.info(f"Nachname eingegeben mit: {selector}")
|
||||
lastname_filled = True
|
||||
break
|
||||
|
||||
if not lastname_filled:
|
||||
logger.error("Fehler beim Eingeben des Nachnamens")
|
||||
return False
|
||||
|
||||
# Geburtsdatum
|
||||
# Geburtsdatum - Verbesserte Dropdown-Behandlung
|
||||
birth_date = account_data["birth_date"]
|
||||
|
||||
# Tag auswählen
|
||||
if not self.automation.browser.select_option(
|
||||
# Tag auswählen mit Fallback
|
||||
day_selectors = [
|
||||
self.selectors.REG_BIRTHDAY_DAY,
|
||||
str(birth_date["day"])
|
||||
):
|
||||
self.selectors.REG_BIRTHDAY_DAY_ALT,
|
||||
"select[aria-label='Tag']",
|
||||
"select[title='Tag']"
|
||||
]
|
||||
day_selected = False
|
||||
for selector in day_selectors:
|
||||
try:
|
||||
if self.automation.browser.select_option(selector, str(birth_date["day"])):
|
||||
logger.info(f"Tag {birth_date['day']} ausgewählt mit: {selector}")
|
||||
day_selected = True
|
||||
break
|
||||
except:
|
||||
continue
|
||||
|
||||
if not day_selected:
|
||||
logger.error("Fehler beim Auswählen des Geburtstags")
|
||||
return False
|
||||
|
||||
# Monat auswählen
|
||||
if not self.automation.browser.select_option(
|
||||
self.automation.human_behavior.random_delay(0.3, 0.5)
|
||||
|
||||
# Monat auswählen mit Fallback
|
||||
month_selectors = [
|
||||
self.selectors.REG_BIRTHDAY_MONTH,
|
||||
str(birth_date["month"])
|
||||
):
|
||||
self.selectors.REG_BIRTHDAY_MONTH_ALT,
|
||||
"select[aria-label='Monat']",
|
||||
"select[title='Monat']"
|
||||
]
|
||||
month_selected = False
|
||||
for selector in month_selectors:
|
||||
try:
|
||||
if self.automation.browser.select_option(selector, str(birth_date["month"])):
|
||||
logger.info(f"Monat {birth_date['month']} ausgewählt mit: {selector}")
|
||||
month_selected = True
|
||||
break
|
||||
except:
|
||||
continue
|
||||
|
||||
if not month_selected:
|
||||
logger.error("Fehler beim Auswählen des Geburtsmonats")
|
||||
return False
|
||||
|
||||
# Jahr auswählen
|
||||
if not self.automation.browser.select_option(
|
||||
self.automation.human_behavior.random_delay(0.3, 0.5)
|
||||
|
||||
# Jahr auswählen mit Fallback
|
||||
year_selectors = [
|
||||
self.selectors.REG_BIRTHDAY_YEAR,
|
||||
str(birth_date["year"])
|
||||
):
|
||||
self.selectors.REG_BIRTHDAY_YEAR_ALT,
|
||||
"select[aria-label='Jahr']",
|
||||
"select[title='Jahr']"
|
||||
]
|
||||
year_selected = False
|
||||
for selector in year_selectors:
|
||||
try:
|
||||
if self.automation.browser.select_option(selector, str(birth_date["year"])):
|
||||
logger.info(f"Jahr {birth_date['year']} ausgewählt mit: {selector}")
|
||||
year_selected = True
|
||||
break
|
||||
except:
|
||||
continue
|
||||
|
||||
if not year_selected:
|
||||
logger.error("Fehler beim Auswählen des Geburtsjahrs")
|
||||
return False
|
||||
|
||||
self.automation.human_behavior.random_delay(0.5, 1.0)
|
||||
|
||||
# Geschlecht auswählen
|
||||
# Geschlecht auswählen - Verbesserte Radio-Button Behandlung
|
||||
gender_selector = self.selectors.get_gender_selector(account_data["gender"])
|
||||
if not self.automation.browser.click_element(gender_selector):
|
||||
gender_selected = False
|
||||
|
||||
# Versuche erst direkten Click auf das Input-Element
|
||||
if self.automation.browser.click_element(gender_selector):
|
||||
logger.info(f"Geschlecht direkt ausgewählt: {account_data['gender']}")
|
||||
gender_selected = True
|
||||
else:
|
||||
# Fallback: Klicke auf das Label
|
||||
label_selectors = [
|
||||
f"label:has-text('{'Weiblich' if account_data['gender'] == 'female' else 'Männlich' if account_data['gender'] == 'male' else 'Divers'}')",
|
||||
f"label._58mt:has(input[value='{'1' if account_data['gender'] == 'female' else '2' if account_data['gender'] == 'male' else '-1'}'])"
|
||||
]
|
||||
for selector in label_selectors:
|
||||
try:
|
||||
if self.automation.browser.click_element(selector):
|
||||
logger.info(f"Geschlecht über Label ausgewählt: {account_data['gender']}")
|
||||
gender_selected = True
|
||||
break
|
||||
except:
|
||||
continue
|
||||
|
||||
if not gender_selected:
|
||||
logger.error(f"Fehler beim Auswählen des Geschlechts: {account_data['gender']}")
|
||||
return False
|
||||
|
||||
self.automation.human_behavior.random_delay(0.5, 1.0)
|
||||
|
||||
# E-Mail oder Telefonnummer
|
||||
contact_field = account_data.get("email") or account_data.get("phone_number")
|
||||
if not contact_field:
|
||||
logger.error("Keine E-Mail oder Telefonnummer angegeben")
|
||||
# E-Mail eingeben mit Fallback
|
||||
email_field = account_data.get("email")
|
||||
if not email_field:
|
||||
logger.error("Keine E-Mail-Adresse angegeben")
|
||||
return False
|
||||
|
||||
if not self.automation.ui_helper.type_text_human_like(
|
||||
email_selectors = [
|
||||
self.selectors.REG_EMAIL_OR_PHONE,
|
||||
contact_field
|
||||
):
|
||||
logger.error("Fehler beim Eingeben der Kontaktdaten")
|
||||
self.selectors.REG_EMAIL_OR_PHONE_ALT,
|
||||
"input[placeholder*='E-Mail']",
|
||||
"input[placeholder*='Handynummer oder E-Mail']"
|
||||
]
|
||||
email_filled = False
|
||||
for selector in email_selectors:
|
||||
if self.automation.browser.is_element_visible(selector, timeout=1000):
|
||||
if self.automation.ui_helper.type_text_human_like(selector, email_field):
|
||||
logger.info(f"E-Mail eingegeben mit: {selector}")
|
||||
email_filled = True
|
||||
break
|
||||
|
||||
if not email_filled:
|
||||
logger.error("Fehler beim Eingeben der E-Mail")
|
||||
return False
|
||||
|
||||
# Warte auf mögliches E-Mail-Bestätigungsfeld
|
||||
self.automation.human_behavior.random_delay(1.0, 2.0)
|
||||
|
||||
# Wenn E-Mail eingegeben wurde, könnte ein Bestätigungsfeld erscheinen
|
||||
if account_data.get("email"):
|
||||
if self.automation.browser.is_element_visible(self.selectors.REG_EMAIL_CONFIRM, timeout=2000):
|
||||
logger.info("E-Mail-Bestätigungsfeld erkannt")
|
||||
if not self.automation.ui_helper.type_text_human_like(
|
||||
self.selectors.REG_EMAIL_CONFIRM,
|
||||
account_data["email"]
|
||||
):
|
||||
logger.warning("Fehler beim Bestätigen der E-Mail")
|
||||
# E-Mail-Bestätigung falls erforderlich
|
||||
if self.automation.browser.is_element_visible(self.selectors.REG_EMAIL_CONFIRM, timeout=2000):
|
||||
logger.info("E-Mail-Bestätigungsfeld erkannt")
|
||||
if not self.automation.ui_helper.type_text_human_like(
|
||||
self.selectors.REG_EMAIL_CONFIRM,
|
||||
email_field
|
||||
):
|
||||
logger.warning("Fehler beim Bestätigen der E-Mail")
|
||||
|
||||
# Passwort
|
||||
if not self.automation.ui_helper.type_text_human_like(
|
||||
# Passwort mit Fallback
|
||||
password_selectors = [
|
||||
self.selectors.REG_PASSWORD,
|
||||
account_data["password"]
|
||||
):
|
||||
self.selectors.REG_PASSWORD_ALT,
|
||||
self.selectors.REG_PASSWORD_ALT2,
|
||||
"input[type='password']",
|
||||
"input[autocomplete='new-password']"
|
||||
]
|
||||
password_filled = False
|
||||
for selector in password_selectors:
|
||||
if self.automation.browser.is_element_visible(selector, timeout=1000):
|
||||
if self.automation.ui_helper.type_text_human_like(selector, account_data["password"]):
|
||||
logger.info(f"Passwort eingegeben mit: {selector}")
|
||||
password_filled = True
|
||||
break
|
||||
|
||||
if not password_filled:
|
||||
logger.error("Fehler beim Eingeben des Passworts")
|
||||
return False
|
||||
|
||||
@ -522,30 +696,68 @@ class FacebookRegistration:
|
||||
def _enter_verification_code(self, code: str) -> bool:
|
||||
"""
|
||||
Gibt den Verifikationscode ein.
|
||||
Verbesserte Version für 5-stelligen Code mit Fallback-Selektoren.
|
||||
|
||||
Args:
|
||||
code: Verifikationscode
|
||||
code: Verifikationscode (5-stellig, nur Zahlen)
|
||||
|
||||
Returns:
|
||||
bool: True bei Erfolg
|
||||
"""
|
||||
try:
|
||||
# Extrahiere nur Zahlen aus dem Code (falls FB- prefix vorhanden)
|
||||
import re
|
||||
code_digits = re.sub(r'\D', '', code)
|
||||
if len(code_digits) == 5:
|
||||
code = code_digits
|
||||
logger.info(f"Gebe Verifikationscode ein: {code}")
|
||||
|
||||
# Code eingeben
|
||||
if not self.automation.ui_helper.type_text_human_like(
|
||||
self.selectors.VERIFICATION_CODE_INPUT,
|
||||
code
|
||||
):
|
||||
logger.error("Fehler beim Eingeben des Verifikationscodes")
|
||||
# Versuche verschiedene Selektoren für das Code-Eingabefeld
|
||||
code_selectors = [
|
||||
self.selectors.VERIFICATION_CODE_INPUT, # input#code_in_cliff
|
||||
self.selectors.VERIFICATION_CODE_INPUT_ALT, # input[name='code']
|
||||
self.selectors.VERIFICATION_CODE_INPUT_ALT2, # input[maxlength='5']
|
||||
"input[size='5']", # 5-stelliges Feld
|
||||
"input[type='text'][maxlength='5']", # Text-Input mit 5 Zeichen
|
||||
"input[placeholder*='Code']", # Placeholder mit 'Code'
|
||||
]
|
||||
|
||||
code_entered = False
|
||||
for selector in code_selectors:
|
||||
try:
|
||||
if self.automation.browser.is_element_visible(selector, timeout=1000):
|
||||
# Stelle sicher, dass das Feld leer ist
|
||||
self.automation.browser.page.locator(selector).first.clear()
|
||||
self.automation.human_behavior.random_delay(0.2, 0.4)
|
||||
|
||||
# Gebe Code ein
|
||||
if self.automation.ui_helper.type_text_human_like(selector, code):
|
||||
logger.info(f"Verifikationscode eingegeben mit: {selector}")
|
||||
code_entered = True
|
||||
break
|
||||
except:
|
||||
continue
|
||||
|
||||
if not code_entered:
|
||||
logger.error("Fehler beim Eingeben des Verifikationscodes - kein Eingabefeld gefunden")
|
||||
return False
|
||||
|
||||
self.automation.human_behavior.random_delay(0.5, 1.0)
|
||||
|
||||
# Weiter-Button klicken
|
||||
continue_clicked = False
|
||||
|
||||
# Versuche verschiedene Selektoren
|
||||
for text in self.selectors.get_button_texts("continue"):
|
||||
selector = f"button:has-text('{text}')"
|
||||
# Versuche verschiedene Button-Selektoren
|
||||
continue_selectors = [
|
||||
self.selectors.VERIFICATION_CONTINUE_BUTTON, # button:has-text('Weiter')
|
||||
self.selectors.VERIFICATION_CONTINUE_BUTTON_EN, # button:has-text('Continue')
|
||||
"button[type='submit']", # Submit-Button
|
||||
"button:has-text('Bestätigen')", # Bestätigen
|
||||
"button:has-text('Confirm')", # Englisch
|
||||
"button:has-text('OK')", # OK
|
||||
]
|
||||
|
||||
for selector in continue_selectors:
|
||||
try:
|
||||
if self.automation.browser.click_element(selector, timeout=1000):
|
||||
logger.info(f"Verifikation fortgesetzt mit: {selector}")
|
||||
@ -554,18 +766,35 @@ class FacebookRegistration:
|
||||
except:
|
||||
continue
|
||||
|
||||
# Oder Enter drücken
|
||||
# Fallback: Enter drücken
|
||||
if not continue_clicked:
|
||||
self.automation.browser.page.keyboard.press("Enter")
|
||||
logger.info("Verifikation mit Enter fortgesetzt")
|
||||
continue_clicked = True
|
||||
|
||||
# Warte auf Navigation
|
||||
self.automation.human_behavior.wait_for_page_load()
|
||||
if not continue_clicked:
|
||||
logger.error("Konnte Verifikation nicht fortsetzen")
|
||||
return False
|
||||
|
||||
# Warte auf Navigation/Verarbeitung
|
||||
self.automation.human_behavior.wait_for_page_load(multiplier=1.5)
|
||||
|
||||
# Prüfe auf OK-Button (Popup nach erfolgreicher Verifikation)
|
||||
if self.automation.browser.is_element_visible(self.selectors.VERIFICATION_OK_BUTTON, timeout=3000):
|
||||
self.automation.browser.click_element(self.selectors.VERIFICATION_OK_BUTTON)
|
||||
logger.info("OK-Button nach Verifikation geklickt")
|
||||
ok_selectors = [
|
||||
self.selectors.VERIFICATION_OK_BUTTON,
|
||||
self.selectors.VERIFICATION_OK_BUTTON_ALT,
|
||||
"a:has-text('OK')",
|
||||
"button:has-text('OK')"
|
||||
]
|
||||
|
||||
for selector in ok_selectors:
|
||||
try:
|
||||
if self.automation.browser.is_element_visible(selector, timeout=2000):
|
||||
self.automation.browser.click_element(selector)
|
||||
logger.info(f"OK-Button nach Verifikation geklickt: {selector}")
|
||||
break
|
||||
except:
|
||||
continue
|
||||
|
||||
return True
|
||||
|
||||
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren