autoUpload/utils/enhanced_human_typing.py

233 lines
8.0 KiB
Python

import time
import random
import re
import asyncio
from typing import Dict, List, Optional
class EnhancedHumanTypingSimulator:
def __init__(self, page=None):
# 保留原方案的简单配置
self.base_config = {
'min_typing_speed': 5,
'max_typing_speed': 15,
'pause_probability': 0.1,
'chunk_input': True,
'max_chunk_length': 50
}
# 新增高级特性配置
self.advanced_config = {
# 人类状态模拟
'energy_level': random.uniform(0.7, 1.0),
'typing_proficiency': random.uniform(0.6, 0.9),
'emotion_state': random.uniform(0.8, 1.0),
# 错误处理
'base_error_rate': random.uniform(0.02, 0.05),
'error_correction_speed': random.uniform(0.3, 0.8),
# 速度控制
'speed_variance': random.uniform(0.1, 0.2),
'burst_speed_probability': 0.1
}
self.page = page
self.typing_session = {
'start_time': None,
'chars_typed': 0,
'last_break_time': time.time()
}
async def type_text(self, text: str, selector: str = None) -> bool:
"""增强版的文本输入方法"""
try:
if selector:
# 等待并点击元素
await self._prepare_input(selector)
# 初始化会话
self.typing_session['start_time'] = time.time()
# 智能分段
chunks = self._smart_split_text(text)
for chunk in chunks:
# 获取当前状态
current_state = self._get_current_state()
# 输入当前段落
await self._type_chunk(chunk, current_state)
# 段落间自然停顿
await self._natural_pause(current_state)
return True
except Exception as e:
print(f"输入文本时出错: {e}")
return False
def _smart_split_text(self, text: str) -> List[str]:
"""智能文本分段"""
paragraphs = text.split('\n')
chunks = []
for para in paragraphs:
if len(para) <= self.base_config['max_chunk_length']:
if para.strip():
chunks.append(para)
continue
sentences = re.split(r'([。!?,:;])', para)
current_chunk = ''
for sent in sentences:
if len(current_chunk) + len(sent) < self.base_config['max_chunk_length']:
current_chunk += sent
else:
if current_chunk.strip():
chunks.append(current_chunk)
current_chunk = sent
if current_chunk.strip():
chunks.append(current_chunk)
return chunks
def _get_current_state(self) -> Dict:
"""获取当前输入状态"""
typing_duration = time.time() - self.typing_session['start_time']
fatigue = min(typing_duration / 300, 0.7)
self.advanced_config['energy_level'] *= (1 - fatigue * 0.1)
self.advanced_config['emotion_state'] *= random.uniform(0.98, 1.02)
return {
'energy_level': max(0.3, self.advanced_config['energy_level']),
'emotion_state': max(0.4, min(1.0, self.advanced_config['emotion_state'])),
'typing_proficiency': self.advanced_config['typing_proficiency'],
'current_error_rate': self._calculate_error_rate(fatigue)
}
async def _type_chunk(self, chunk: str, state: Dict):
"""输入文本块"""
for char in chunk:
typing_speed = self._calculate_typing_speed(state)
if random.random() < state['current_error_rate']:
await self._handle_typing_error(char, state)
else:
await self._type_char(char, typing_speed)
self.typing_session['chars_typed'] += 1
await self._micro_pause(state)
def _calculate_typing_speed(self, state: Dict) -> float:
"""计算实时打字速度"""
base_speed = random.uniform(
self.base_config['min_typing_speed'],
self.base_config['max_typing_speed']
)
speed = base_speed * (
0.7 + state['energy_level'] * 0.3 +
state['emotion_state'] * 0.2 +
state['typing_proficiency'] * 0.3
)
speed *= random.uniform(
1 - self.advanced_config['speed_variance'],
1 + self.advanced_config['speed_variance']
)
return speed
def _calculate_error_rate(self, fatigue: float) -> float:
"""计算当前错误率"""
base_rate = self.advanced_config['base_error_rate']
error_rate = base_rate * (1 + fatigue)
error_rate *= random.uniform(0.8, 1.2)
return min(error_rate, 0.15)
async def _handle_typing_error(self, char: str, state: Dict):
"""处理打字错误"""
error_types = ['typo', 'double_hit', 'delay']
error_type = random.choice(error_types)
if error_type == 'typo':
wrong_char = self._get_similar_char(char)
await self._type_char(wrong_char, self._calculate_typing_speed(state))
await asyncio.sleep(random.uniform(0.2, 0.5))
await self._press_key("Backspace")
await self._type_char(char, self._calculate_typing_speed(state))
elif error_type == 'double_hit':
await self._type_char(char, self._calculate_typing_speed(state))
await self._type_char(char, self._calculate_typing_speed(state))
await asyncio.sleep(random.uniform(0.1, 0.3))
await self._press_key("Backspace")
else: # delay
await asyncio.sleep(random.uniform(0.3, 0.8))
await self._type_char(char, self._calculate_typing_speed(state))
async def _natural_pause(self, state: Dict):
"""自然停顿"""
base_pause = random.uniform(0.5, 1.5)
if state['energy_level'] < 0.5:
base_pause *= 1.3
if state['emotion_state'] < 0.6:
base_pause *= 1.2
await asyncio.sleep(base_pause * random.uniform(0.8, 1.2))
async def _micro_pause(self, state: Dict):
"""字符间的微小停顿"""
pause_time = random.uniform(0.05, 0.15)
if state['energy_level'] < 0.5:
pause_time *= 1.2
await asyncio.sleep(pause_time)
def _get_similar_char(self, char: str) -> str:
"""获取相似字符"""
similar_chars = {
'': '地得',
'': '着啦',
'': '与跟',
'': '我我',
'': '市师',
'': '再在',
'': '又有',
'': '都读',
'': '号毫'
}
return random.choice(similar_chars.get(char, char + char))
async def _prepare_input(self, selector: str):
"""准备输入"""
try:
await self.page.wait_for_selector(selector, timeout=5000)
await self.page.click(selector)
await asyncio.sleep(random.uniform(0.3, 0.8))
except Exception as e:
print(f"准备输入失败: {e}")
raise
async def _type_char(self, char: str, speed: float):
"""输入单个字符"""
try:
delay = 1000 / speed # 转换为毫秒
await self.page.keyboard.type(char, delay=delay)
except Exception as e:
print(f"输入字符失败: {e}")
raise
async def _press_key(self, key: str):
"""按键操作"""
try:
await self.page.keyboard.press(key)
except Exception as e:
print(f"按键操作失败: {e}")
raise