OCR截屏前点击消息面板设焦点(TIM默认焦点在会话列表,VK_END只滚滚会话列表)+加详细OCR处理日志(stage normalize/clean/split)

This commit is contained in:
youpaishidifu
2026-07-26 19:35:54 +08:00
parent 54d474a6c5
commit 2ccb677abf
+18 -1
View File
@@ -649,6 +649,19 @@ class MessageMonitor:
# 先切 QQ 到前台再截屏,避免 CMD 窗口遮挡→OCR 读到终端文字
self._ensure_foreground(hwnd)
time.sleep(0.15)
# 点一下消息面板区域设置焦点(TIM 默认焦点在会话列表,VK_END 只会滚会话列表)
try:
click_x = int(win_w * 0.72) # 消息面板中心偏右
click_y = int(win_h * 0.50)
lparam = win32api.MAKELONG(click_x, click_y)
win32gui.PostMessage(hwnd, win32con.WM_LBUTTONDOWN, win32con.MK_LBUTTON, lparam)
win32gui.PostMessage(hwnd, win32con.WM_LBUTTONUP, 0, lparam)
logger.debug(f"[qq] 点击消息面板({click_x},{click_y})设置焦点")
time.sleep(0.15)
except Exception as e:
logger.debug(f"[qq] 点击消息面板失败: {e}")
# Ctrl+End 滚动到底部,只截最新消息(避开历史堆积+bot 旧回复)
VK_CONTROL = 0x11
VK_END = 0x23
@@ -710,18 +723,22 @@ class MessageMonitor:
# QQ NT OCR 将所有可见消息合并为一段无换行文本,消息间以时间戳分隔
# 按时间戳分割恢复独立消息,避免整坨变成一条"新消息"
expanded = []
for rl in ocr_lines:
for i, rl in enumerate(ocr_lines):
before = rl
rl = self._normalize_ocr_text(rl)
logger.debug(f"[ocr] stage[{i}] normalize: {before[:50]!r} -> {rl[:50]!r}")
# 先清理 & 碎片(OCR 把时间戳右边缘的 : 读成 &)
# 必须在时间戳分割前做,否则 "13:5&07" 无法被时间戳正则捕获
rl = rl.replace('&', '')
# 把全角 :统一成半角 :,让后续正则统一匹配
rl = rl.replace(':', ':')
logger.debug(f"[ocr] stage[{i}] clean: {rl[:80]!r}")
# 分割"msg1 14:24 msg2 13:27 msg3" → ["msg1", "msg2", "msg3"]
# 使用更宽松的 \d{1,2}(允许单数字),因为 & 移除后 "5&07"→"507"
# 打破的时间戳如 "13:5 07" 也尽量捕获
rl = re.sub(r'\s+', ' ', rl) # 多重空格压为一个
parts = re.split(r'(\d{1,2}:\d{1,2}(?::\d{1,2})?)', rl)
logger.debug(f"[ocr] stage[{i}] split -> {len(parts)} parts: {[p[:30] for p in parts if p.strip()]}")
buf = ''
for part in parts:
if re.match(r'^\d{1,2}:\d{1,2}', part):