Files
AccountForger-neuerUpload/social_networks/tiktok/tiktok_selectors.py
Claude Project Manager ea8fddce97 TikTok läuft wieder
2025-08-12 13:41:21 +02:00

228 Zeilen
9.3 KiB
Python

"""
TikTok-Selektoren - CSS-Selektoren und XPath-Ausdrücke für die TikTok-Automatisierung
Mit Text-Matching-Funktionen für robuste Element-Erkennung
"""
from typing import List, Dict, Optional, Any
class TikTokSelectors:
"""
Zentrale Sammlung aller Selektoren für die TikTok-Automatisierung.
Bei Änderungen der TikTok-Webseite müssen nur hier Anpassungen vorgenommen werden.
Enthält auch Fuzzy-Text-Matching-Daten für robustere Element-Erkennung.
"""
# URL-Konstanten
BASE_URL = "https://www.tiktok.com"
SIGNUP_URL = "https://www.tiktok.com/signup"
LOGIN_URL = "https://www.tiktok.com/login"
EXPLORE_URL = "https://www.tiktok.com/explore"
# Anmelden/Registrieren-Buttons Hauptseite
LOGIN_BUTTON = "button#header-login-button"
LOGIN_BUTTON_HEADER = "button#header-login-button"
LOGIN_BUTTON_CLASS = "button.TUXButton:has-text('Anmelden')"
LOGIN_BUTTON_LEFT = "button#header-login-button"
LOGIN_BUTTON_RIGHT = "button#top-right-action-bar-login-button"
LOGIN_BUTTON_TOP = "button#header-login-button"
LOGIN_BUTTON_TOP_RIGHT = "button#top-right-action-bar-login-button"
LOGIN_BUTTON_SIDEBAR = "button[data-e2e='login-button-sidebar']"
LOGIN_BUTTON_FALLBACK = "//button[contains(text(), 'Anmelden')]"
SIGNUP_LINK = "span[data-e2e='bottom-sign-up']"
SIGNUP_LINK_FALLBACK = "a[href*='/signup']"
# Login-Dialog Optionen
LOGIN_DIALOG = "div[role='dialog']"
LOGIN_EMAIL_PHONE_OPTION = "div[data-e2e='channel-item']"
LOGIN_EMAIL_USERNAME_LINK = "a[href='/login/phone-or-email/email']"
# Cookie-Dialog
COOKIE_DIALOG = "div[role='dialog'][data-testid='cookie-banner']"
COOKIE_ACCEPT_BUTTON = "button[data-testid='accept-all-cookies']"
# Registrierungsdialog - Methoden
REGISTER_DIALOG_TITLE = "h1:contains('Registrieren')"
REGISTER_LINK = "a:contains('Registrieren')"
REGISTER_LINK_FALLBACK = "//a[contains(text(), 'Registrieren')]"
REGISTRATION_DIALOG = "div[role='dialog']"
PHONE_EMAIL_BUTTON = "div[data-e2e='channel-item']"
PHONE_EMAIL_OPTION = "div[data-e2e='channel-item']"
PHONE_EMAIL_OPTION_FALLBACK = "//div[contains(text(), 'Telefonnummer oder E-Mail')]"
EMAIL_OPTION = "a[href*='/signup/phone-or-email/email']"
EMAIL_OPTION_FALLBACK = "//a[contains(text(), 'E-Mail')]"
PHONE_OPTION = "a[href*='/signup/phone-or-email/phone']"
PHONE_OPTION_FALLBACK = "//a[contains(text(), 'Telefon')]"
REGISTER_WITH_EMAIL = "a[href*='/signup/phone-or-email/email']"
REGISTER_WITH_PHONE = "a[href*='/signup/phone-or-email/phone']"
# Geburtsdatum-Selektoren
BIRTHDAY_MONTH_DROPDOWN = "select[name='month']"
BIRTHDAY_DAY_DROPDOWN = "select[name='day']"
BIRTHDAY_YEAR_DROPDOWN = "select[name='year']"
BIRTHDAY_MONTH_SELECT = "div.css-1leicpq-DivSelectLabel:contains('Monat')"
BIRTHDAY_DAY_SELECT = "div.css-1leicpq-DivSelectLabel:contains('Tag')"
BIRTHDAY_YEAR_SELECT = "div.css-1leicpq-DivSelectLabel:contains('Jahr')"
BIRTHDAY_DROPDOWN_OPTION = "div[role='option']"
BIRTHDAY_DROPDOWN_CONTAINER = "div.css-1leicpq-DivSelectLabel"
BIRTHDAY_ARROW = "svg.css-gz151e-StyledArrowTriangleDownLargeFill"
# Formularfelder - E-Mail-Registrierung
EMAIL_FIELD = "input[placeholder='E-Mail-Adresse']"
EMAIL_FIELD_ALT = "input[name='email']"
PASSWORD_FIELD = "input[placeholder='Passwort']"
PASSWORD_FIELD_ALT = "input[type='password']"
VERIFICATION_CODE_FIELD = "input[placeholder*='sechsstelligen Code']"
VERIFICATION_CODE_FIELD_ALT = "input[placeholder='Gib den sechsstelligen Code ein']"
USERNAME_FIELD = "input[placeholder='Benutzername']"
USERNAME_FIELD_ALT = "input[name='new-username']"
# Formularfelder - Telefon-Registrierung
COUNTRY_CODE_SELECT = "div[role='combobox']"
PHONE_FIELD = "input[placeholder='Telefonnummer']"
# Buttons
SEND_CODE_BUTTON = "button[data-e2e='send-code-button']"
SEND_CODE_BUTTON_ALT = "button.css-1jjb4td-ButtonSendCode"
SEND_CODE_BUTTON_ALT2 = "button[class*='ButtonSendCode']"
SEND_CODE_BUTTON_TEXT = "button:has-text('Code senden')"
RESEND_CODE_BUTTON = "button:contains('Code erneut senden')"
CONTINUE_BUTTON = "button[type='submit']"
CONTINUE_BUTTON_ALT = "button.e1w6iovg0"
REGISTER_BUTTON = "button:contains('Registrieren')"
REGISTER_BUTTON_ALT = "button[type='submit']:contains('Registrieren')"
SKIP_BUTTON = "div:contains('Überspringen')"
SKIP_BUTTON_ALT = "div.css-4y1w75-DivTextContainer"
SKIP_USERNAME_BUTTON = "button:contains('Überspringen')"
# Checkbox
NEWSLETTER_CHECKBOX = "input[type='checkbox']"
# Login-Formularfelder
LOGIN_EMAIL_FIELD = "input[name='username'][placeholder='E-Mail-Adresse oder Benutzername']"
LOGIN_EMAIL_FIELD_ALT = "input.tiktok-11to27l-InputContainer[name='username']"
LOGIN_PASSWORD_FIELD = "input[type='password'][placeholder='Passwort']"
LOGIN_PASSWORD_FIELD_ALT = "input.tiktok-wv3bkt-InputContainer[type='password']"
LOGIN_SUBMIT_BUTTON = "button[type='submit'][data-e2e='login-button']"
LOGIN_SUBMIT_BUTTON_ALT = "button.tiktok-11sviba-Button-StyledButton[data-e2e='login-button']"
# Erfolgs-Indikatoren für Registrierung
SUCCESS_INDICATORS = [
"a[href='/foryou']",
"a[href='/explore']",
"button[data-e2e='profile-icon']",
"svg[data-e2e='profile-icon']"
]
# Links für Nutzungsbedingungen und Datenschutz
TERMS_LINK = "a:contains('Nutzungsbedingungen')"
PRIVACY_LINK = "a:contains('Datenschutzerklärung')"
# Login-Fehler
ERROR_MESSAGE = "span.error-message"
LOGIN_ERROR_CONTAINER = "div[class*='error']"
# Text-Matching-Parameter für Fuzzy-Matching
TEXT_MATCH = {
# Formularfelder
"form_fields": {
"email": ["E-Mail-Adresse", "E-Mail", "Email", "Mail"],
"phone": ["Telefonnummer", "Telefon", "Phone", "Mobile"],
"password": ["Passwort", "Password"],
"verification_code": ["Bestätigungscode", "Code", "Verifizierungscode", "Sicherheitscode"],
"username": ["Benutzername", "Username", "Name"]
},
# Buttons
"buttons": {
"send_code": ["Code senden", "Senden", "Send code", "Verification code", "Send"],
"continue": ["Weiter", "Continue", "Next", "Fortfahren"],
"register": ["Registrieren", "Register", "Sign up", "Konto erstellen"],
"skip": ["Überspringen", "Skip", "Later", "Später", "Nicht jetzt"],
},
# Fehler-Indikatoren
"error_indicators": [
"Fehler", "Error", "Leider", "Ungültig", "Invalid", "Nicht verfügbar",
"Fehlgeschlagen", "Problem", "Failed", "Nicht möglich", "Bereits verwendet",
"Too many attempts", "Zu viele Versuche", "Rate limit", "Bitte warte"
],
# Bestätigungscode-Texte in E-Mails
"email_verification_patterns": [
"ist dein Bestätigungscode",
"ist dein TikTok-Code",
"is your TikTok code",
"is your verification code",
"Dein Bestätigungscode lautet",
"Your verification code is"
],
# E-Mail-Betreff-Muster für TikTok
"email_subject_patterns": [
"ist dein Bestätigungscode",
"is your confirmation code",
"TikTok verification code",
"TikTok Bestätigungscode"
]
}
@classmethod
def get_field_labels(cls, field_type: str) -> List[str]:
"""
Gibt die möglichen Bezeichnungen für ein Formularfeld zurück.
Args:
field_type: Typ des Formularfelds (z.B. "email", "phone")
Returns:
List[str]: Liste mit möglichen Bezeichnungen
"""
return cls.TEXT_MATCH["form_fields"].get(field_type, [])
@classmethod
def get_button_texts(cls, button_type: str) -> List[str]:
"""
Gibt die möglichen Texte für einen Button zurück.
Args:
button_type: Typ des Buttons (z.B. "send_code", "continue")
Returns:
List[str]: Liste mit möglichen Button-Texten
"""
return cls.TEXT_MATCH["buttons"].get(button_type, [])
@classmethod
def get_error_indicators(cls) -> List[str]:
"""
Gibt die möglichen Texte für Fehlerindikatoren zurück.
Returns:
List[str]: Liste mit möglichen Fehlerindikator-Texten
"""
return cls.TEXT_MATCH["error_indicators"]
@classmethod
def get_email_verification_patterns(cls) -> List[str]:
"""
Gibt die möglichen Texte für Bestätigungscodes in E-Mails zurück.
Returns:
List[str]: Liste mit möglichen E-Mail-Bestätigungscode-Texten
"""
return cls.TEXT_MATCH["email_verification_patterns"]
@classmethod
def get_month_option_selector(cls, month: int) -> str:
"""Returns selector for month option."""
return f"option[value='{month}']"
@classmethod
def get_day_option_selector(cls, day: int) -> str:
"""Returns selector for day option."""
return f"option[value='{day}']"
@classmethod
def get_year_option_selector(cls, year: int) -> str:
"""Returns selector for year option."""
return f"option[value='{year}']"