Update changes
Dieser Commit ist enthalten in:
@ -24,18 +24,21 @@ class HumanBehavior:
|
||||
self.speed_factor = max(0.1, min(10.0, speed_factor)) # Begrenzung auf 0.1-10.0
|
||||
self.randomness = max(0.0, min(1.0, randomness)) # Begrenzung auf 0.0-1.0
|
||||
|
||||
# Typische Verzögerungen (in Sekunden)
|
||||
# Typische Verzögerungen (in Sekunden) - ERHÖHT für Anti-Detection
|
||||
self.delays = {
|
||||
"typing_per_char": 0.05, # Verzögerung pro Zeichen beim Tippen
|
||||
"typing_per_char": 0.08, # Verzögerung pro Zeichen beim Tippen (erhöht)
|
||||
"mouse_movement": 0.5, # Verzögerung für Mausbewegung
|
||||
"click": 0.1, # Verzögerung für Mausklick
|
||||
"page_load": 2.0, # Verzögerung für das Laden einer Seite
|
||||
"form_fill": 1.0, # Verzögerung zwischen Formularfeldern
|
||||
"decision": 1.5, # Verzögerung für Entscheidungen
|
||||
"scroll": 0.3, # Verzögerung für Scrollbewegungen
|
||||
"verification": 5.0, # Verzögerung für Verifizierungsprozesse
|
||||
"image_upload": 3.0, # Verzögerung für Bildupload
|
||||
"navigation": 1.0 # Verzögerung für Navigation
|
||||
"click": 0.15, # Verzögerung für Mausklick (erhöht)
|
||||
"page_load": 8.0, # Verzögerung für das Laden einer Seite (STARK erhöht: 5-15s)
|
||||
"form_fill": 4.0, # Verzögerung zwischen Formularfeldern (STARK erhöht: 2-8s)
|
||||
"decision": 3.0, # Verzögerung für Entscheidungen (erhöht)
|
||||
"scroll": 0.5, # Verzögerung für Scrollbewegungen (erhöht)
|
||||
"verification": 30.0, # Verzögerung für Verifizierungsprozesse (STARK erhöht: 15-45s)
|
||||
"image_upload": 5.0, # Verzögerung für Bildupload (erhöht)
|
||||
"navigation": 2.0, # Verzögerung für Navigation (erhöht)
|
||||
"cookie_reading": 5.0, # NEU: Cookie-Banner lesen (3-8s)
|
||||
"field_transition": 5.0, # NEU: Zwischen Formularfeldern (2-8s)
|
||||
"thinking": 2.0 # NEU: Kurze Denkpause
|
||||
}
|
||||
|
||||
def sleep(self, delay_type: str, multiplier: float = 1.0) -> None:
|
||||
@ -76,7 +79,7 @@ class HumanBehavior:
|
||||
def _random_delay(self, min_seconds: float = 1.0, max_seconds: float = 3.0) -> None:
|
||||
"""
|
||||
Führt eine zufällige Wartezeit aus, um menschliches Verhalten zu simulieren.
|
||||
|
||||
|
||||
Args:
|
||||
min_seconds: Minimale Wartezeit in Sekunden
|
||||
max_seconds: Maximale Wartezeit in Sekunden
|
||||
@ -84,42 +87,96 @@ class HumanBehavior:
|
||||
delay = random.uniform(min_seconds, max_seconds)
|
||||
logger.debug(f"Zufällige Wartezeit: {delay:.2f} Sekunden")
|
||||
time.sleep(delay)
|
||||
|
||||
def type_text(self, text: str, on_char_typed: Optional[Callable[[str], None]] = None,
|
||||
error_probability: float = 0.05, correction_probability: float = 0.9) -> str:
|
||||
|
||||
def anti_detection_delay(self, action_type: str = "form_fill") -> None:
|
||||
"""
|
||||
Simuliert menschliches Tippen mit möglichen Tippfehlern und Korrekturen.
|
||||
|
||||
Erzeugt eine realistische Anti-Detection-Verzögerung.
|
||||
|
||||
Diese Methode verwendet längere, zufälligere Wartezeiten um Bot-Erkennung
|
||||
zu vermeiden. Die Verzögerungen sind bewusst lang um menschliches
|
||||
Verhalten realistischer zu simulieren.
|
||||
|
||||
Args:
|
||||
action_type: Art der Aktion:
|
||||
- "form_fill": Zwischen Formularfeldern (2-8s)
|
||||
- "page_load": Auf neuen Seiten (5-15s)
|
||||
- "verification": Vor Code-Eingabe (15-45s)
|
||||
- "cookie_reading": Cookie-Banner lesen (3-8s)
|
||||
- "thinking": Kurze Denkpause (1-3s)
|
||||
"""
|
||||
delay_ranges = {
|
||||
"form_fill": (2.0, 8.0), # Zwischen Formularfeldern
|
||||
"page_load": (5.0, 15.0), # Auf neuen Seiten
|
||||
"verification": (15.0, 45.0), # Vor Code-Eingabe
|
||||
"cookie_reading": (3.0, 8.0), # Cookie-Banner lesen
|
||||
"thinking": (1.0, 3.0), # Kurze Denkpause
|
||||
"field_focus": (0.5, 1.5), # Vor Feldinteraktion
|
||||
}
|
||||
|
||||
min_delay, max_delay = delay_ranges.get(action_type, (2.0, 5.0))
|
||||
|
||||
# Basis-Verzögerung
|
||||
delay = random.uniform(min_delay, max_delay)
|
||||
|
||||
# Zusätzliche Variation basierend auf randomness
|
||||
if self.randomness > 0:
|
||||
variation = 1.0 + (random.random() * 2 - 1) * self.randomness * 0.3
|
||||
delay *= variation
|
||||
|
||||
# Speed-Factor anwenden (aber nicht zu stark reduzieren)
|
||||
delay = delay / max(self.speed_factor, 0.5)
|
||||
|
||||
# Gelegentlich extra lange Pause (simuliert Ablenkung/Nachdenken)
|
||||
if random.random() < 0.1:
|
||||
extra_delay = random.uniform(2.0, 5.0)
|
||||
delay += extra_delay
|
||||
logger.debug(f"Extra Denkpause: +{extra_delay:.2f}s")
|
||||
|
||||
logger.debug(f"Anti-Detection Delay ({action_type}): {delay:.2f}s")
|
||||
time.sleep(max(0.5, delay)) # Minimum 0.5s
|
||||
|
||||
def type_text(self, text: str, on_char_typed: Optional[Callable[[str], None]] = None,
|
||||
error_probability: float = 0.15, correction_probability: float = 0.95) -> str:
|
||||
"""
|
||||
Simuliert menschliches Tippen mit realistischen Tippfehlern und Korrekturen.
|
||||
|
||||
Die Fehlerrate wurde auf 15% erhöht (vorher 5%) um realistischeres
|
||||
menschliches Verhalten zu simulieren. Echte Menschen machen häufig
|
||||
Tippfehler und korrigieren diese sofort.
|
||||
|
||||
Args:
|
||||
text: Zu tippender Text
|
||||
on_char_typed: Optionale Funktion, die für jedes getippte Zeichen aufgerufen wird
|
||||
error_probability: Wahrscheinlichkeit für Tippfehler (0-1)
|
||||
error_probability: Wahrscheinlichkeit für Tippfehler (0-1), Standard: 0.15 (15%)
|
||||
correction_probability: Wahrscheinlichkeit, Tippfehler zu korrigieren (0-1)
|
||||
|
||||
|
||||
Returns:
|
||||
Der tatsächlich getippte Text (mit oder ohne Fehler)
|
||||
"""
|
||||
# Anpassen der Fehlerwahrscheinlichkeit basierend auf Zufälligkeit
|
||||
adjusted_error_prob = error_probability * self.randomness
|
||||
|
||||
# Fehlerrate zwischen 10-20% halten für Realismus
|
||||
base_error_prob = max(0.10, min(0.20, error_probability))
|
||||
# Anpassen basierend auf Zufälligkeit (aber nicht unter 10%)
|
||||
adjusted_error_prob = max(0.10, base_error_prob * (0.8 + self.randomness * 0.4))
|
||||
|
||||
result = ""
|
||||
i = 0
|
||||
|
||||
|
||||
while i < len(text):
|
||||
char = text[i]
|
||||
|
||||
|
||||
# Potentieller Tippfehler
|
||||
if random.random() < adjusted_error_prob:
|
||||
# Auswahl eines Fehlertyps:
|
||||
# - Falsches Zeichen (Tastatur-Nachbarn)
|
||||
# - Ausgelassenes Zeichen
|
||||
# - Doppeltes Zeichen
|
||||
# Auswahl eines Fehlertyps:
|
||||
# - Falsches Zeichen (Tastatur-Nachbarn) - 50%
|
||||
# - Transposition (Buchstaben vertauschen) - 15%
|
||||
# - Ausgelassenes Zeichen - 15%
|
||||
# - Doppeltes Zeichen - 20%
|
||||
error_type = random.choices(
|
||||
["wrong", "skip", "double"],
|
||||
weights=[0.6, 0.2, 0.2],
|
||||
["wrong", "transposition", "skip", "double"],
|
||||
weights=[0.50, 0.15, 0.15, 0.20],
|
||||
k=1
|
||||
)[0]
|
||||
|
||||
|
||||
if error_type == "wrong":
|
||||
# Falsches Zeichen tippen (Tastatur-Nachbarn)
|
||||
keyboard_neighbors = self.get_keyboard_neighbors(char)
|
||||
@ -129,15 +186,18 @@ class HumanBehavior:
|
||||
if on_char_typed:
|
||||
on_char_typed(wrong_char)
|
||||
self.sleep("typing_per_char")
|
||||
|
||||
|
||||
# Pause bevor Fehler "bemerkt" wird
|
||||
time.sleep(random.uniform(0.1, 0.4))
|
||||
|
||||
# Entscheiden, ob der Fehler korrigiert wird
|
||||
if random.random() < correction_probability:
|
||||
# Löschen des falschen Zeichens
|
||||
result = result[:-1]
|
||||
if on_char_typed:
|
||||
on_char_typed("\b") # Backspace
|
||||
self.sleep("typing_per_char", 1.5) # Längere Pause für Korrektur
|
||||
|
||||
self.sleep("typing_per_char", 1.8)
|
||||
|
||||
# Korrektes Zeichen tippen
|
||||
result += char
|
||||
if on_char_typed:
|
||||
@ -149,35 +209,87 @@ class HumanBehavior:
|
||||
if on_char_typed:
|
||||
on_char_typed(char)
|
||||
self.sleep("typing_per_char")
|
||||
|
||||
|
||||
elif error_type == "transposition" and i < len(text) - 1:
|
||||
# Buchstaben vertauschen (häufiger Tippfehler)
|
||||
next_char = text[i + 1]
|
||||
result += next_char + char # Vertauscht
|
||||
if on_char_typed:
|
||||
on_char_typed(next_char)
|
||||
self.sleep("typing_per_char")
|
||||
on_char_typed(char)
|
||||
self.sleep("typing_per_char")
|
||||
|
||||
# Korrektur der Transposition
|
||||
if random.random() < correction_probability:
|
||||
time.sleep(random.uniform(0.2, 0.5)) # Bemerken des Fehlers
|
||||
# Beide Zeichen löschen
|
||||
result = result[:-2]
|
||||
if on_char_typed:
|
||||
on_char_typed("\b")
|
||||
self.sleep("typing_per_char", 1.3)
|
||||
on_char_typed("\b")
|
||||
self.sleep("typing_per_char", 1.5)
|
||||
|
||||
# Korrekte Reihenfolge tippen
|
||||
result += char + next_char
|
||||
if on_char_typed:
|
||||
on_char_typed(char)
|
||||
self.sleep("typing_per_char")
|
||||
on_char_typed(next_char)
|
||||
self.sleep("typing_per_char")
|
||||
|
||||
i += 1 # Nächstes Zeichen überspringen (bereits verarbeitet)
|
||||
|
||||
elif error_type == "skip":
|
||||
# Zeichen auslassen (nichts tun)
|
||||
# In 50% der Fälle später bemerken und nachtippen
|
||||
if random.random() < 0.5 and i < len(text) - 1:
|
||||
# Nächstes Zeichen normal tippen
|
||||
pass # Wird übersprungen
|
||||
pass
|
||||
|
||||
|
||||
elif error_type == "double":
|
||||
# Zeichen doppelt tippen
|
||||
result += char + char
|
||||
if on_char_typed:
|
||||
on_char_typed(char)
|
||||
self.sleep("typing_per_char", 0.3) # Sehr kurz zwischen Doppel
|
||||
on_char_typed(char)
|
||||
self.sleep("typing_per_char")
|
||||
|
||||
|
||||
# Pause bevor Fehler bemerkt wird
|
||||
time.sleep(random.uniform(0.15, 0.35))
|
||||
|
||||
# Entscheiden, ob der Fehler korrigiert wird
|
||||
if random.random() < correction_probability:
|
||||
# Löschen des doppelten Zeichens
|
||||
result = result[:-1]
|
||||
if on_char_typed:
|
||||
on_char_typed("\b") # Backspace
|
||||
self.sleep("typing_per_char", 1.2)
|
||||
self.sleep("typing_per_char", 1.3)
|
||||
else:
|
||||
# Normales Tippen ohne Fehler
|
||||
result += char
|
||||
if on_char_typed:
|
||||
on_char_typed(char)
|
||||
self.sleep("typing_per_char")
|
||||
|
||||
|
||||
# Variable Tippgeschwindigkeit basierend auf Zeichen
|
||||
if char in ' .,!?;:':
|
||||
# Längere Pause nach Satzzeichen/Leerzeichen
|
||||
self.sleep("typing_per_char", random.uniform(1.2, 1.8))
|
||||
elif char.isupper():
|
||||
# Leicht länger für Großbuchstaben (Shift-Taste)
|
||||
self.sleep("typing_per_char", random.uniform(1.0, 1.3))
|
||||
else:
|
||||
self.sleep("typing_per_char", random.uniform(0.8, 1.2))
|
||||
|
||||
i += 1
|
||||
|
||||
|
||||
# Gelegentliche längere Pause (Nachdenken)
|
||||
if random.random() < 0.05:
|
||||
time.sleep(random.uniform(0.3, 0.8))
|
||||
|
||||
return result
|
||||
|
||||
def get_keyboard_neighbors(self, char: str) -> List[str]:
|
||||
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren