Files
AccountForger-neuerUpload/utils/human_behavior.py
Claude Project Manager a25a26a01a Update changes
2026-01-18 18:15:34 +01:00

704 Zeilen
30 KiB
Python

"""
Menschliches Verhalten für den Social Media Account Generator.
"""
import random
import time
import logging
import math
from typing import Optional, Tuple, List, Dict, Any, Callable
logger = logging.getLogger("human_behavior")
class HumanBehavior:
"""Klasse zur Simulation von menschlichem Verhalten für die Automatisierung."""
def __init__(self, speed_factor: float = 1.0, randomness: float = 0.5):
"""
Initialisiert die HumanBehavior-Klasse.
Args:
speed_factor: Faktormultiplikator für die Geschwindigkeit (höher = schneller)
randomness: Faktor für die Zufälligkeit (0-1, höher = zufälliger)
"""
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) - ERHÖHT für Anti-Detection
self.delays = {
"typing_per_char": 0.08, # Verzögerung pro Zeichen beim Tippen (erhöht)
"mouse_movement": 0.5, # Verzögerung für Mausbewegung
"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:
"""
Pausiert die Ausführung für eine bestimmte Zeit, basierend auf dem Verzögerungstyp.
Args:
delay_type: Typ der Verzögerung (aus self.delays)
multiplier: Zusätzlicher Multiplikator für die Verzögerung
"""
base_delay = self.delays.get(delay_type, 0.5) # Standardverzögerung, wenn der Typ nicht bekannt ist
# Berechne die effektive Verzögerung
delay = base_delay * multiplier / self.speed_factor
# Füge Zufälligkeit hinzu
if self.randomness > 0:
# Variiere die Verzögerung um ±randomness%
variation = 1.0 + (random.random() * 2 - 1) * self.randomness
delay *= variation
# Stelle sicher, dass die Verzögerung nicht negativ ist
delay = max(0, delay)
logger.debug(f"Schlafe für {delay:.2f}s ({delay_type})")
time.sleep(delay)
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
"""
return self._random_delay(min_seconds, max_seconds)
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
"""
delay = random.uniform(min_seconds, max_seconds)
logger.debug(f"Zufällige Wartezeit: {delay:.2f} Sekunden")
time.sleep(delay)
def anti_detection_delay(self, action_type: str = "form_fill") -> None:
"""
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), Standard: 0.15 (15%)
correction_probability: Wahrscheinlichkeit, Tippfehler zu korrigieren (0-1)
Returns:
Der tatsächlich getippte Text (mit oder ohne Fehler)
"""
# 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) - 50%
# - Transposition (Buchstaben vertauschen) - 15%
# - Ausgelassenes Zeichen - 15%
# - Doppeltes Zeichen - 20%
error_type = random.choices(
["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)
if keyboard_neighbors:
wrong_char = random.choice(keyboard_neighbors)
result += wrong_char
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.8)
# Korrektes Zeichen tippen
result += char
if on_char_typed:
on_char_typed(char)
self.sleep("typing_per_char")
else:
# Wenn keine Nachbarn gefunden werden, normales Zeichen tippen
result += char
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.3)
else:
# Normales Tippen ohne Fehler
result += char
if on_char_typed:
on_char_typed(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]:
"""
Gibt die Tastatur-Nachbarn eines Zeichens zurück.
Args:
char: Das Zeichen, für das Nachbarn gefunden werden sollen
Returns:
Liste von benachbarten Zeichen
"""
# QWERTY-Tastaturlayout
keyboard_layout = {
"1": ["2", "q"],
"2": ["1", "3", "q", "w"],
"3": ["2", "4", "w", "e"],
"4": ["3", "5", "e", "r"],
"5": ["4", "6", "r", "t"],
"6": ["5", "7", "t", "y"],
"7": ["6", "8", "y", "u"],
"8": ["7", "9", "u", "i"],
"9": ["8", "0", "i", "o"],
"0": ["9", "-", "o", "p"],
"-": ["0", "=", "p", "["],
"=": ["-", "[", "]"],
"q": ["1", "2", "w", "a"],
"w": ["2", "3", "q", "e", "a", "s"],
"e": ["3", "4", "w", "r", "s", "d"],
"r": ["4", "5", "e", "t", "d", "f"],
"t": ["5", "6", "r", "y", "f", "g"],
"y": ["6", "7", "t", "u", "g", "h"],
"u": ["7", "8", "y", "i", "h", "j"],
"i": ["8", "9", "u", "o", "j", "k"],
"o": ["9", "0", "i", "p", "k", "l"],
"p": ["0", "-", "o", "[", "l", ";"],
"[": ["-", "=", "p", "]", ";", "'"],
"]": ["=", "[", "'", "\\"],
"a": ["q", "w", "s", "z"],
"s": ["w", "e", "a", "d", "z", "x"],
"d": ["e", "r", "s", "f", "x", "c"],
"f": ["r", "t", "d", "g", "c", "v"],
"g": ["t", "y", "f", "h", "v", "b"],
"h": ["y", "u", "g", "j", "b", "n"],
"j": ["u", "i", "h", "k", "n", "m"],
"k": ["i", "o", "j", "l", "m", ","],
"l": ["o", "p", "k", ";", ",", "."],
";": ["p", "[", "l", "'", ".", "/"],
"'": ["[", "]", ";", "/"],
"z": ["a", "s", "x"],
"x": ["s", "d", "z", "c"],
"c": ["d", "f", "x", "v"],
"v": ["f", "g", "c", "b"],
"b": ["g", "h", "v", "n"],
"n": ["h", "j", "b", "m"],
"m": ["j", "k", "n", ","],
",": ["k", "l", "m", "."],
".": ["l", ";", ",", "/"],
"/": [";", "'", "."],
" ": ["c", "v", "b", "n", "m"] # Leertaste hat viele benachbarte Tasten
}
# Für Großbuchstaben die Nachbarn der Kleinbuchstaben verwenden
if char.lower() != char and char.lower() in keyboard_layout:
return [neighbor.upper() if random.choice([True, False]) else neighbor
for neighbor in keyboard_layout[char.lower()]]
return keyboard_layout.get(char, [])
def mouse_move(self, from_point: Optional[Tuple[int, int]] = None,
to_point: Tuple[int, int] = (0, 0),
on_move: Optional[Callable[[Tuple[int, int]], None]] = None) -> None:
"""
Simuliert eine menschliche Mausbewegung mit natürlicher Beschleunigung und Verzögerung.
Args:
from_point: Startpunkt der Bewegung (oder None für aktuelle Position)
to_point: Zielpunkt der Bewegung
on_move: Optionale Funktion, die für jede Zwischenposition aufgerufen wird
"""
# Wenn kein Startpunkt angegeben ist, einen zufälligen verwenden
if from_point is None:
from_point = (random.randint(0, 1000), random.randint(0, 800))
# Berechne die Entfernung
dx = to_point[0] - from_point[0]
dy = to_point[1] - from_point[1]
distance = (dx**2 + dy**2)**0.5
# Anzahl der Zwischenschritte basierend auf der Entfernung
# Mehr Schritte für realistischere Bewegung
steps = max(20, int(distance / 5))
# Wähle zufällig einen Bewegungstyp
movement_type = random.choice(["bezier", "arc", "zigzag", "smooth"])
if movement_type == "bezier":
# Bézierkurve mit mehr Variation
control_variance = distance / 4
control_point_1 = (
from_point[0] + dx * random.uniform(0.2, 0.4) + random.randint(-int(control_variance), int(control_variance)),
from_point[1] + dy * random.uniform(0.1, 0.3) + random.randint(-int(control_variance), int(control_variance))
)
control_point_2 = (
from_point[0] + dx * random.uniform(0.6, 0.8) + random.randint(-int(control_variance), int(control_variance)),
from_point[1] + dy * random.uniform(0.7, 0.9) + random.randint(-int(control_variance), int(control_variance))
)
else:
# Standard Kontrollpunkte für andere Bewegungstypen
control_point_1 = (from_point[0] + dx * 0.3, from_point[1] + dy * 0.3)
control_point_2 = (from_point[0] + dx * 0.7, from_point[1] + dy * 0.7)
# Micro-Pauses und Geschwindigkeitsvariationen
micro_pause_probability = 0.1
speed_variations = [0.5, 0.8, 1.0, 1.2, 1.5]
# Bewegung durchführen
for i in range(steps + 1):
t = i / steps
if movement_type == "bezier":
# Kubische Bézierkurve
x = (1-t)**3 * from_point[0] + 3*(1-t)**2*t * control_point_1[0] + 3*(1-t)*t**2 * control_point_2[0] + t**3 * to_point[0]
y = (1-t)**3 * from_point[1] + 3*(1-t)**2*t * control_point_1[1] + 3*(1-t)*t**2 * control_point_2[1] + t**3 * to_point[1]
elif movement_type == "arc":
# Bogenbewegung
arc_height = distance * 0.2 * (1 if random.random() > 0.5 else -1)
x = from_point[0] + dx * t
y = from_point[1] + dy * t + arc_height * 4 * t * (1-t)
elif movement_type == "zigzag":
# Zickzack-Bewegung
zigzag_amplitude = distance * 0.05
x = from_point[0] + dx * t + zigzag_amplitude * math.sin(t * math.pi * 4)
y = from_point[1] + dy * t
else: # smooth
# Glatte S-Kurve
s_curve = t * t * (3 - 2 * t)
x = from_point[0] + dx * s_curve
y = from_point[1] + dy * s_curve
# Füge leichtes "Zittern" hinzu für mehr Realismus
if self.randomness > 0.3:
jitter = 2 * self.randomness
x += random.uniform(-jitter, jitter)
y += random.uniform(-jitter, jitter)
# Runde auf ganze Zahlen
curr_point = (int(x), int(y))
# Callback aufrufen, wenn vorhanden
if on_move:
on_move(curr_point)
# Micro-Pause einbauen
if random.random() < micro_pause_probability:
time.sleep(random.uniform(0.05, 0.2))
# Variable Geschwindigkeit
speed_factor = random.choice(speed_variations)
# Verzögerung basierend auf der Position in der Bewegung
# Am Anfang und Ende langsamer, in der Mitte schneller
if i < 0.15 * steps or i > 0.85 * steps:
self.sleep("mouse_movement", 2.0 * speed_factor / steps)
elif i < 0.3 * steps or i > 0.7 * steps:
self.sleep("mouse_movement", 1.5 * speed_factor / steps)
else:
self.sleep("mouse_movement", 0.8 * speed_factor / steps)
def click(self, double: bool = False, right: bool = False) -> None:
"""
Simuliert einen Mausklick mit menschlicher Verzögerung.
Args:
double: True für Doppelklick, False für Einzelklick
right: True für Rechtsklick, False für Linksklick
"""
click_type = "right" if right else "left"
click_count = 2 if double else 1
for _ in range(click_count):
logger.debug(f"{click_type.capitalize()}-Klick")
self.sleep("click")
if double and _ == 0:
# Kürzere Pause zwischen Doppelklicks
self.sleep("click", 0.3)
def scroll(self, direction: str = "down", amount: int = 5,
on_scroll: Optional[Callable[[int], None]] = None) -> None:
"""
Simuliert Scrollen mit menschlicher Verzögerung.
Args:
direction: "up" oder "down"
amount: Anzahl der Scroll-Ereignisse
on_scroll: Optionale Funktion, die für jedes Scroll-Ereignis aufgerufen wird
"""
if direction not in ["up", "down"]:
logger.warning(f"Ungültige Scrollrichtung: {direction}")
return
# Vorzeichenwechsel für die Richtung
scroll_factor = -1 if direction == "up" else 1
# Wähle ein Scroll-Pattern
patterns = ["smooth", "reading", "fast_scan", "search", "momentum"]
pattern = random.choice(patterns)
logger.debug(f"Verwende Scroll-Pattern: {pattern}")
# Pattern-spezifische Parameter
if pattern == "smooth":
# Gleichmäßiges Scrollen
for i in range(amount):
scroll_amount = scroll_factor * random.randint(2, 4)
if on_scroll:
on_scroll(scroll_amount)
if i < amount - 1:
self.sleep("scroll", random.uniform(0.8, 1.2))
elif pattern == "reading":
# Lese-Pattern: langsam mit Pausen
for i in range(amount):
scroll_amount = scroll_factor * 1
if on_scroll:
on_scroll(scroll_amount)
if i < amount - 1:
if random.random() < 0.3: # 30% Chance für Lese-Pause
time.sleep(random.uniform(0.5, 2.0))
else:
self.sleep("scroll", random.uniform(1.5, 2.5))
elif pattern == "fast_scan":
# Schnelles Überfliegen
for i in range(amount):
scroll_amount = scroll_factor * random.randint(5, 8)
if on_scroll:
on_scroll(scroll_amount)
if i < amount - 1:
self.sleep("scroll", random.uniform(0.1, 0.3))
elif pattern == "search":
# Suchen-Pattern: unregelmäßig, vor und zurück
total_scrolled = 0
for i in range(amount):
if random.random() < 0.2 and total_scrolled > 5: # 20% Chance zurückzuscrollen
scroll_amount = -scroll_factor * random.randint(1, 3)
else:
scroll_amount = scroll_factor * random.randint(2, 5)
total_scrolled += abs(scroll_amount)
if on_scroll:
on_scroll(scroll_amount)
if i < amount - 1:
self.sleep("scroll", random.uniform(0.3, 1.0))
else: # momentum
# Momentum-Scrolling (wie Touch-Geräte)
initial_speed = random.randint(8, 12)
deceleration = 0.85
current_speed = initial_speed
while current_speed > 0.5 and amount > 0:
scroll_amount = scroll_factor * int(current_speed)
if on_scroll:
on_scroll(scroll_amount)
current_speed *= deceleration
amount -= 1
if amount > 0:
self.sleep("scroll", 0.05) # Sehr kurze Pausen für flüssige Bewegung
# Gelegentliches "Overscroll" und Bounce-Back
if random.random() < 0.1 and pattern != "momentum":
time.sleep(0.1)
if on_scroll:
on_scroll(-scroll_factor * 2) # Kleiner Bounce-Back
def wait_for_page_load(self, multiplier: float = 1.0) -> None:
"""
Wartet eine angemessene Zeit auf das Laden einer Seite.
Args:
multiplier: Multiplikator für die Standardwartezeit
"""
self.sleep("page_load", multiplier)
def wait_between_actions(self, action_type: str = "decision", multiplier: float = 1.0) -> None:
"""
Wartet zwischen Aktionen, um menschliches Verhalten zu simulieren.
Args:
action_type: Art der Aktion
multiplier: Multiplikator für die Standardwartezeit
"""
self.sleep(action_type, multiplier)
def navigate_sequence(self, steps: int, min_delay: float = 0.5, max_delay: float = 2.0) -> None:
"""
Simuliert eine Sequenz von Navigationsschritten mit variierenden Verzögerungen.
Args:
steps: Anzahl der Navigationsschritte
min_delay: Minimale Verzögerung zwischen Schritten
max_delay: Maximale Verzögerung zwischen Schritten
"""
for i in range(steps):
# Zufällige Verzögerung zwischen Navigationsschritten
delay = random.uniform(min_delay, max_delay)
logger.debug(f"Navigationsschritt {i+1}/{steps}, Verzögerung: {delay:.2f}s")
time.sleep(delay / self.speed_factor)
def human_delay_pattern(self, action_type: str = "default", intensity: str = "medium") -> None:
"""
Erzeugt ein komplexes, menschliches Verzögerungsmuster.
Args:
action_type: Art der Aktion (entscheidet über Basismuster)
intensity: Intensität des Musters ("low", "medium", "high")
"""
# Verzögerungsmuster basierend auf Aktionstyp und Intensität
patterns = {
"default": {
"low": (0.2, 0.5),
"medium": (0.5, 1.0),
"high": (1.0, 2.0)
},
"reading": {
"low": (1.0, 2.0),
"medium": (2.0, 4.0),
"high": (3.0, 6.0)
},
"thinking": {
"low": (1.5, 3.0),
"medium": (3.0, 5.0),
"high": (5.0, 8.0)
},
"verification": {
"low": (3.0, 5.0),
"medium": (5.0, 8.0),
"high": (8.0, 12.0)
}
}
# Standardmuster verwenden, wenn nicht bekannt
pattern = patterns.get(action_type, patterns["default"])
delay_range = pattern.get(intensity, pattern["medium"])
# Zufällige Verzögerung im angegebenen Bereich
delay = random.uniform(delay_range[0], delay_range[1])
# Anpassung basierend auf Geschwindigkeit und Zufälligkeit
delay = delay / self.speed_factor
if self.randomness > 0:
# Füge ein zufälliges "Zittern" hinzu
jitter = random.uniform(-0.2, 0.2) * self.randomness * delay
delay += jitter
logger.debug(f"Menschliche Verzögerung ({action_type}, {intensity}): {delay:.2f}s")
time.sleep(max(0, delay))
def simulate_form_filling(self, fields: int, field_callback: Optional[Callable[[int], None]] = None) -> None:
"""
Simuliert das Ausfüllen eines Formulars mit menschlichem Verhalten.
Args:
fields: Anzahl der auszufüllenden Felder
field_callback: Optionale Funktion, die für jedes Feld aufgerufen wird
"""
for i in range(fields):
logger.debug(f"Fülle Formularfeld {i+1}/{fields} aus")
if field_callback:
field_callback(i)
# Verzögerung zwischen Feldern
if i < fields - 1: # Keine Verzögerung nach dem letzten Feld
# Gelegentlich längere Pausen einbauen
if random.random() < 0.2 * self.randomness:
self.human_delay_pattern("thinking", "low")
else:
self.sleep("form_fill")
def simulate_captcha_solving(self, on_progress: Optional[Callable[[float], None]] = None) -> None:
"""
Simuliert das Lösen eines CAPTCHAs mit menschlichem Verhalten.
Args:
on_progress: Optionale Funktion, die mit dem Fortschritt (0-1) aufgerufen wird
"""
# Simuliere einen komplexen Prozess mit mehreren Schritten
steps = random.randint(4, 8)
for i in range(steps):
progress = (i + 1) / steps
logger.debug(f"CAPTCHA-Lösung Fortschritt: {progress:.0%}")
if on_progress:
on_progress(progress)
# Verschiedene Verzögerungsmuster für die einzelnen Schritte
if i == 0:
# Anfängliches Lesen/Verstehen
self.human_delay_pattern("reading", "medium")
elif i == steps - 1:
# Abschließende Überprüfung/Bestätigung
self.human_delay_pattern("verification", "low")
else:
# Auswahl/Interaktion
self.human_delay_pattern("thinking", "medium")