前言
"接口也是口,算法也是算",综合来看就是口算!
看到全网都在炸鱼也忍不住来玩一玩...
参考了大佬的OCR版,试用后发现影响速度的最大卡点并不是识别速度等,而是""由于检测异常导致的等待"。
基于体验几局的感受------输入对了可以极速跳题、答题成功会有提示音,便将思路放到了从音量检测入手。
实现
思路大致几点------
1、输入对了可以极速跳题。
2、答题成功会有提示音。
3、目前没有看到过输入"="的场景,仅有大于和小于。
基于上述三点,暴力作答所需猜测的情况也只有两种,且作答成功后可快速进行下一题,减少卡顿,理论可行。
因此,尝试不通过ORC识别或其他方式来判断题目作答正确,而是采取"是否曝出了提示音""来判断是否作答正确。
流程大致为:
1、作答符号为">"。
- 如果有提示音,短停留继续作答。
- 如果没有提示音, 长停留继续作答。
2、切换作答符号为另一个。
由此循环往复...
代码
需自行安装虚拟声卡,用于让Python检测声音。
python
import pyautogui
import time
import numpy as np
import pyaudio
from pynput.mouse import Controller, Button
from pynput.keyboard import Listener, Key
# 初始化鼠标控制器
mouse = Controller()
# 全局变量,控制绘制状态
running = False
prev_volume = 0 # 上一个音量值
def log_message(message):
"""记录日志消息"""
current_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
print(f"[{current_time}] {message}")
def draw_symbol(symbol):
"""绘制符号"""
screen_width, screen_height = pyautogui.size()
x = int(screen_width * 0.4) # 水平居中
y = int(screen_height * 0.7) # 将 y 坐标设置为屏幕高度的 70%
duration = 0.03 # 每条线的持续时间
rect_size = 40 # 控制绘制符号的大小(线条长度的控制)
if symbol == '>':
# 绘制 ">" 符号
mouse.position = (x, y)
mouse.press(Button.left)
mouse.move(rect_size, rect_size) # 右下斜线
time.sleep(duration)
mouse.move(-rect_size, rect_size) # 左下斜线
time.sleep(duration)
mouse.release(Button.left)
log_message("执行了绘制 '>' 符号 操作")
elif symbol == '<':
# 绘制 "<" 符号
mouse.position = (x, y)
mouse.press(Button.left)
mouse.move(-rect_size, rect_size) # 左下斜线
time.sleep(duration)
mouse.move(rect_size, rect_size) # 右下斜线
time.sleep(duration)
mouse.release(Button.left)
log_message("执行了绘制 '<' 符号 操作")
def list_audio_devices():
"""列出可用的音频输入设备"""
p = pyaudio.PyAudio()
log_message("可用的音频设备:")
for i in range(p.get_device_count()):
info = p.get_device_info_by_index(i)
log_message(f"设备 {i}: {info['name']} - {'输入' if info['maxInputChannels'] > 0 else '输出'}")
p.terminate()
def get_supported_sample_rates(device_index):
"""获取指定设备支持的采样率"""
p = pyaudio.PyAudio()
device_info = p.get_device_info_by_index(device_index)
log_message(f"设备 {device_index} ({device_info['name']}) 支持的采样率: {device_info['defaultSampleRate']}")
p.terminate()
return int(device_info['defaultSampleRate'])
def detect_system_sound(threshold=1000, device_index=24): # 使用设备索引 24
"""检测系统声音并返回是否检测到突然增加的声音"""
global prev_volume # 声明使用全局变量
chunk = 1024 # 每次读取的音频块大小
sample_rate = get_supported_sample_rates(device_index) # 获取支持的采样率
p = pyaudio.PyAudio()
# 打开音频流,确保输入设备是虚拟音频设备
stream = p.open(format=pyaudio.paInt16, channels=1,
rate=sample_rate, input=True,
frames_per_buffer=chunk, input_device_index=device_index)
audio_data = stream.read(chunk)
audio_data_np = np.frombuffer(audio_data, dtype=np.int16)
volume_norm = np.linalg.norm(audio_data_np) / np.sqrt(chunk) # 计算音量(RMS)
stream.stop_stream()
stream.close()
p.terminate()
log_message(f"当前音量:{volume_norm:.2f}") # 打印当前音量以调试
# 检测音量的突然增加
if volume_norm > prev_volume + threshold:
prev_volume = volume_norm # 更新上一个音量值
return True # 检测到声音突增
else:
prev_volume = volume_norm # 更新上一个音量值
return False # 未检测到声音突增
def toggle_running(key):
"""切换运行状态"""
global running
if key == Key.enter: # 当按下 Enter 键时切换状态
running = not running
if running:
log_message("绘图已启动...")
else:
log_message("绘图已停止。")
def main():
global running
log_message("按 Enter 键启动或停止绘图...")
i = 0
# 列出可用的音频设备
list_audio_devices()
# 启动键盘监听
with Listener(on_press=toggle_running) as listener:
while True:
if running:
# 检测声音
sound_detected = detect_system_sound()
if sound_detected:
log_message("有检测到声音突增!")
time.sleep(0.2) # 如果检测到声音突增,等待 0.2 秒
else:
log_message("未检测到声音突增,等待 1 秒...")
time.sleep(0.8) # 如果未检测到声音,等待 1 秒
# 绘制 "<" 符号
if i % 2:
draw_symbol('<')
else:
draw_symbol('>')
i += 1
# 换行分隔
log_message("")
time.sleep(0.1) # 避免占用过多 CPU 资源
if __name__ == "__main__":
main()
优化点。
1、由于小猿口算的Bug------即背景音乐无法关闭。导致检测声音突增并不是那么准确。同时吐槽一下,小猿官方没有对用户名违禁进行检测吗?头像+用户名均sex居然可以过审,难以想象。
2、模拟器产生声音 - Python检测到变化,会有一定的延迟。
综合测试来看,感觉可能并不比单纯的暴力快多少,因此此尝试更多的还是------整活。