From 1738daffeca83a59d85e98c182b21a20addf33b1 Mon Sep 17 00:00:00 2001 From: youpaishidifu Date: Wed, 12 Aug 2026 11:45:50 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=9F=AD=E5=8F=A5=E7=A2=8E?= =?UTF-8?q?=E7=89=87=E5=92=8C=E6=A8=A1=E7=B3=8A=E9=87=8D=E5=A4=8D=E8=B7=B3?= =?UTF-8?q?=E8=BF=87=E7=9A=84=E8=AF=AF=E6=8A=A5=EF=BC=9A=E5=85=81=E8=AE=B8?= =?UTF-8?q?=E5=8C=85=E5=90=AB=E6=8B=AC=E5=8F=B7=E7=9A=84=E7=9F=AD=E6=B6=88?= =?UTF-8?q?=E6=81=AF=EF=BC=8C=E9=97=AE=E5=8F=A5=E4=B8=8D=E8=A7=86=E4=B8=BA?= =?UTF-8?q?=E6=A8=A1=E7=B3=8A=E9=87=8D=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- easyocr_log.txt | 96 ++++++++++++++++++++++++ gui.py | 6 +- monitor.py | 25 +++++-- monitor_logs.py | 192 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 311 insertions(+), 8 deletions(-) create mode 100644 easyocr_log.txt create mode 100644 monitor_logs.py diff --git a/easyocr_log.txt b/easyocr_log.txt new file mode 100644 index 0000000..413ddac --- /dev/null +++ b/easyocr_log.txt @@ -0,0 +1,96 @@ +1:2026-08-08 21:24:25,201 [msgbot] INFO: 消息问答助手启动中... +10:2026-08-08 21:25:12,874 [msgbot.monitor] WARNING: [mem-watch] RSS=645MB threads=37 gdi=118 hash=0 seen=0 garbage={} easyocr_alive=False +11:2026-08-08 21:25:12,874 [msgbot.monitor] INFO: [mem-watch] 内存看门狗已启动(每30s记录 RSS/线程/GDI) +14:2026-08-08 21:25:12,877 [msgbot.monitor] INFO: 消息监控已启动 +18:2026-08-08 21:25:16,225 [msgbot.monitor] DEBUG: [ocr] EasyOCR 子进程已启动,等待初始化握手... +26:2026-08-08 21:25:18,993 [msgbot.monitor] DEBUG: [ocr] EasyOCR 子进程存活但握手未完成,等待就绪(≤60s)... +27:2026-08-08 21:25:24,892 [msgbot.monitor] WARNING: [wechat] _ensure_hwnd 超时(12s),跳过本轮 +28:2026-08-08 21:25:28,993 [msgbot.monitor] WARNING: [qq] EasyOCR 超时(10.0s)线程存活,跳过 +47:2026-08-08 21:25:31,697 [msgbot.monitor] DEBUG: [ocr] EasyOCR 子进程存活但握手未完成,等待就绪(≤60s)... +48:2026-08-08 21:25:31,757 [msgbot.monitor] INFO: [ocr] EasyOCR 子进程就绪 +49:2026-08-08 21:25:31,760 [msgbot.monitor] DEBUG: [ocr] 已截断崩溃日志,清除旧条目 +66:2026-08-08 21:25:40,183 [msgbot.monitor] INFO: [ocr] [easyocr/原始] line[0]: '哪儿能下到登录插件啊?' +67:2026-08-08 21:25:40,184 [msgbot.monitor] INFO: [ocr] [easyocr/原始] line[1]: '等级' +68:2026-08-08 21:25:40,184 [msgbot.monitor] INFO: [ocr] [easyocr/原始] line[2]: '评' +69:2026-08-08 21:25:40,184 [msgbot.monitor] INFO: [ocr] [easyocr/原始] line[3]: '151' +70:2026-08-08 21:25:40,185 [msgbot.monitor] INFO: [ocr] [easyocr/原始] line[4]: '成' +71:2026-08-08 21:25:40,185 [msgbot.monitor] INFO: [ocr] [easyocr/原始] line[5]: '52' +72:2026-08-08 21:25:40,185 [msgbot.monitor] INFO: [ocr] [easyocr/原始] line[6]: '玩家' +73:2026-08-08 21:25:40,185 [msgbot.monitor] INFO: [ocr] [easyocr/原始] line[7]: '53' +74:2026-08-08 21:25:40,185 [msgbot.monitor] INFO: [ocr] [easyocr/原始] line[8]: '成' +75:2026-08-08 21:25:40,186 [msgbot.monitor] INFO: [ocr] [easyocr/原始] line[9]: '54' +76:2026-08-08 21:25:40,186 [msgbot.monitor] INFO: [ocr] [easyocr/原始] line[10]: '成功' +77:2026-08-08 21:25:40,186 [msgbot.monitor] INFO: [ocr] [easyocr/原始] line[11]: '玩家应尊重他人的合法权益;' +78:2026-08-08 21:25:40,186 [msgbot.monitor] INFO: [ocr] [easyocr/原始] line[12]: '不得进行任何形式' +79:2026-08-08 21:25:40,186 [msgbot.monitor] INFO: [ocr] [easyocr/原始] line[13]: '17:42:23' +80:2026-08-08 21:25:40,186 [msgbot.monitor] INFO: [ocr] [easyocr/原始] line[14]: 'PHP的用户端有哪两种登录模式?' +81:2026-08-08 21:25:40,187 [msgbot.monitor] INFO: [ocr] [easyocr/原始] line[15]: '20;22:50' +82:2026-08-08 21:25:40,187 [msgbot.monitor] INFO: [ocr] [easyocr/原始] line[16]: '应该去哪儿下载登录插件?' +83:2026-08-08 21:25:40,187 [msgbot.monitor] INFO: [ocr] [easyocr/原始] line[17]: '玩家应尊重他人的合法权益;' +84:2026-08-08 21:25:40,187 [msgbot.monitor] INFO: [ocr] [easyocr/原始] line[18]: '不得进行任何形式' +85:2026-08-08 21:25:40,187 [msgbot.monitor] INFO: [ocr] [easyocr/原始] line[19]: '[' +86:2026-08-08 21:25:40,188 [msgbot.monitor] DEBUG: [ocr] 引擎对比: win=30.2(行1,字符231) vs easy=45.0(行20,字符135) → 选easyocr(分数差14.8, 胜率100%, 1轮) +107:2026-08-08 21:25:44,211 [msgbot.monitor] WARNING: [mem-watch] RSS=723MB threads=46 gdi=119 hash=2 seen=0 garbage={'qq': 0} easyocr_alive=True +108:2026-08-08 21:25:48,540 [msgbot.monitor] WARNING: [wechat] EasyOCR 超时(10.0s)线程存活,跳过 +174:2026-08-08 21:25:52,422 [msgbot.monitor] WARNING: [qq] EasyOCR 超时(10.0s)线程存活,跳过 +189:2026-08-08 21:25:56,529 [msgbot.monitor] DEBUG: [ocr] EasyOCR 连续3次超时,杀子进程重来 +190:2026-08-08 21:25:57,176 [msgbot.monitor] DEBUG: [ocr] 杀 EasyOCR 子进程(连续超时): terminate 后正常退出 +191:2026-08-08 21:25:57,176 [msgbot.monitor] WARNING: [ocr] 杀 EasyOCR 子进程(连续超时) 诊断: worker死前状态=busy(模式CPU, 上次img长度76816, 更新于2026-08-08T21:25:47.528199,距现在9.0s) | 崩溃日志=2026-08-08 21:25:29.204440 [easyocr_worker] 启动 (pid=28888) +253:2026-08-08 21:25:59,490 [msgbot.monitor] DEBUG: [ocr] EasyOCR 子进程已启动,等待初始化握手... +271:2026-08-08 21:26:08,548 [msgbot.monitor] DEBUG: [ocr] EasyOCR 子进程存活但握手未完成,等待就绪(≤60s)... +272:2026-08-08 21:26:09,474 [msgbot.monitor] WARNING: [qq] EasyOCR 超时(10.0s)线程存活,跳过 +295:2026-08-08 21:26:10,273 [msgbot.monitor] INFO: [ocr] EasyOCR 子进程就绪 +296:2026-08-08 21:26:10,275 [msgbot.monitor] DEBUG: [ocr] 已截断崩溃日志,清除旧条目 +303:2026-08-08 21:26:14,307 [msgbot.monitor] WARNING: [mem-watch] RSS=723MB threads=41 gdi=119 hash=2 seen=0 garbage={'qq': 0, 'wechat': 0} easyocr_alive=True +304:2026-08-08 21:26:18,574 [msgbot.monitor] WARNING: [wechat] EasyOCR 超时(10.0s)线程存活,跳过 +352:2026-08-08 21:26:21,766 [msgbot.monitor] WARNING: [qq] EasyOCR 超时(10.0s)线程存活,跳过 +379:2026-08-08 21:26:26,781 [msgbot.monitor] DEBUG: [ocr] EasyOCR 锁竞争超时(15s),另一线程正在处理中,本次跳过(正常行为) +380:2026-08-08 21:26:26,905 [msgbot.monitor] DEBUG: [ocr] EasyOCR 连续3次超时,杀子进程重来 +381:2026-08-08 21:26:27,541 [msgbot.monitor] DEBUG: [ocr] 杀 EasyOCR 子进程(连续超时): terminate 后正常退出 +382:2026-08-08 21:26:27,541 [msgbot.monitor] WARNING: [ocr] 杀 EasyOCR 子进程(连续超时) 诊断: worker死前状态=busy(模式CPU, 上次img长度76816, 更新于2026-08-08T21:26:17.894109,距现在9.0s) +443:2026-08-08 21:26:29,920 [msgbot.monitor] DEBUG: [ocr] EasyOCR 子进程已启动,等待初始化握手... +459:2026-08-08 21:26:30,933 [msgbot.monitor] DEBUG: [ocr] EasyOCR 子进程存活但握手未完成,等待就绪(≤60s)... +460:2026-08-08 21:26:39,939 [msgbot.monitor] WARNING: [qq] EasyOCR 超时(10.0s)线程存活,跳过 +481:2026-08-08 21:26:40,705 [msgbot.monitor] INFO: [ocr] EasyOCR 子进程就绪 +482:2026-08-08 21:26:40,706 [msgbot.monitor] DEBUG: [ocr] 已截断崩溃日志,清除旧条目 +483:2026-08-08 21:26:40,967 [msgbot.monitor] WARNING: [wechat] EasyOCR 超时(10.0s)线程存活,跳过 +538:2026-08-08 21:26:44,328 [msgbot.monitor] WARNING: [mem-watch] RSS=711MB threads=37 gdi=119 hash=2 seen=0 garbage={'qq': 0, 'wechat': 0} easyocr_alive=True +546:2026-08-08 21:26:52,236 [msgbot.monitor] WARNING: [qq] EasyOCR 超时(10.0s)线程存活,跳过 +572:2026-08-08 21:26:54,711 [msgbot.monitor] WARNING: [wechat] EasyOCR 超时(10.0s)线程存活,跳过 +613:2026-08-08 21:26:57,217 [msgbot.monitor] DEBUG: [ocr] EasyOCR 锁竞争超时(15s),另一线程正在处理中,本次跳过(正常行为) +615:2026-08-08 21:26:57,466 [msgbot.monitor] DEBUG: [ocr] EasyOCR 连续3次超时,杀子进程重来 +623:2026-08-08 21:26:58,134 [msgbot.monitor] DEBUG: [ocr] 杀 EasyOCR 子进程(连续超时): terminate 后正常退出 +624:2026-08-08 21:26:58,135 [msgbot.monitor] WARNING: [ocr] 杀 EasyOCR 子进程(连续超时) 诊断: worker死前状态=busy(模式CPU, 上次img长度76816, 更新于2026-08-08T21:26:48.430053,距现在9.0s) | 崩溃日志=2026-08-08 21:26:38.455250 [easyocr_worker] 启动 (pid=3968) +688:2026-08-08 21:27:00,523 [msgbot.monitor] DEBUG: [ocr] EasyOCR 子进程已启动,等待初始化握手... +705:2026-08-08 21:27:01,544 [msgbot.monitor] DEBUG: [ocr] EasyOCR 子进程存活但握手未完成,等待就绪(≤60s)... +706:2026-08-08 21:27:10,528 [msgbot.monitor] WARNING: [qq] EasyOCR 超时(10.0s)线程存活,跳过 +727:2026-08-08 21:27:11,245 [msgbot.monitor] INFO: [ocr] EasyOCR 子进程就绪 +728:2026-08-08 21:27:11,246 [msgbot.monitor] DEBUG: [ocr] 已截断崩溃日志,清除旧条目 +729:2026-08-08 21:27:11,593 [msgbot.monitor] WARNING: [wechat] EasyOCR 超时(10.0s)线程存活,跳过 +775:2026-08-08 21:27:14,355 [msgbot.monitor] WARNING: [mem-watch] RSS=713MB threads=37 gdi=119 hash=2 seen=0 garbage={'qq': 0, 'wechat': 0} easyocr_alive=True +784:2026-08-08 21:27:22,853 [msgbot.monitor] WARNING: [qq] EasyOCR 超时(10.0s)线程存活,跳过 +810:2026-08-08 21:27:25,161 [msgbot.monitor] WARNING: [wechat] EasyOCR 超时(10.0s)线程存活,跳过 +855:2026-08-08 21:27:27,839 [msgbot.monitor] DEBUG: [ocr] EasyOCR 锁竞争超时(15s),另一线程正在处理中,本次跳过(正常行为) +866:2026-08-08 21:27:27,982 [msgbot.monitor] DEBUG: [ocr] EasyOCR 连续3次超时,杀子进程重来 +874:2026-08-08 21:27:28,633 [msgbot.monitor] DEBUG: [ocr] 杀 EasyOCR 子进程(连续超时): terminate 后正常退出 +875:2026-08-08 21:27:28,633 [msgbot.monitor] WARNING: [ocr] 杀 EasyOCR 子进程(连续超时) 诊断: worker死前状态=busy(模式CPU, 上次img长度76816, 更新于2026-08-08T21:27:18.949094,距现在9.0s) +899:2026-08-08 21:27:28,909 [msgbot.monitor] DEBUG: [ocr] EasyOCR 子进程已启动,等待初始化握手... +908:2026-08-08 21:27:31,079 [msgbot.monitor] WARNING: [wechat] EasyOCR 超时(10.0s)线程存活,跳过 +912:2026-08-08 21:27:31,089 [msgbot.monitor] WARNING: [qq] Windows OCR 超时(10.0s)线程存活,跳过 +913:2026-08-08 21:27:31,089 [msgbot.monitor] WARNING: [qq] EasyOCR 超时(10.0s)线程存活,跳过 +914:2026-08-08 21:27:31,090 [msgbot.monitor] DEBUG: [ocr] EasyOCR 第1次启动失败,冷却(-1786195651s) +916:2026-08-08 21:27:34,032 [msgbot.monitor] ERROR: [ocr] EasyOCR worker 启动即崩溃: +917:2026-08-08 21:27:34,032 [msgbot.monitor] WARNING: [ocr] 检测到静默原生崩溃(无日志), 累计1次,下次可能强制 CPU +918:2026-08-08 21:27:34,032 [msgbot.monitor] DEBUG: [ocr] EasyOCR 冷却中(30s),跳过 +919:2026-08-08 21:27:34,063 [msgbot.monitor] DEBUG: [ocr] 杀 EasyOCR 子进程(stop): terminate 后正常退出 +920:2026-08-08 21:27:34,063 [msgbot.monitor] WARNING: [ocr] 杀 EasyOCR 子进程(stop) 诊断: worker死前状态=busy(模式CPU, 上次img长度76816, 更新于2026-08-08T21:27:18.949094,距现在14.6s) +921:2026-08-08 21:27:34,149 [msgbot.monitor] INFO: 消息监控已停止 +923:2026-08-08 21:27:34,178 [msgbot.monitor] WARNING: [mem-watch] RSS=683MB threads=30 gdi=119 hash=0 seen=0 garbage={} easyocr_alive=False +924:2026-08-08 21:27:34,178 [msgbot.monitor] INFO: [mem-watch] 内存看门狗已启动(每30s记录 RSS/线程/GDI) +927:2026-08-08 21:27:34,180 [msgbot.monitor] INFO: 消息监控已启动 +931:2026-08-08 21:27:35,220 [msgbot.monitor] DEBUG: [ocr] EasyOCR 子进程已启动,等待初始化握手... +937:2026-08-08 21:27:39,510 [msgbot.monitor] ERROR: [ocr] EasyOCR worker 启动即崩溃: +938:2026-08-08 21:27:39,511 [msgbot.monitor] WARNING: [ocr] 检测到静默原生崩溃(无日志), 累计1次,下次可能强制 CPU +939:2026-08-08 21:27:39,539 [msgbot.monitor] DEBUG: [ocr] 杀 EasyOCR 子进程(stop): terminate 后正常退出 +940:2026-08-08 21:27:39,539 [msgbot.monitor] WARNING: [ocr] 杀 EasyOCR 子进程(stop) 诊断: worker死前状态=busy(模式CPU, 上次img长度76816, 更新于2026-08-08T21:27:18.949094,距现在20.0s) +941:2026-08-08 21:27:39,636 [msgbot.monitor] INFO: 消息监控已停止 diff --git a/gui.py b/gui.py index 21ef7fa..5b6e205 100644 --- a/gui.py +++ b/gui.py @@ -346,8 +346,8 @@ def _clean_query_for_kb(msg: str) -> str: t = msg.strip() # 1. 移除QQ群头衔格式: [头衔]用户名 / 【头衔】用户名 t = re.sub(r'[\[【][^】\]]+[】\]]\s*(?:[A-Za-z0-9_\u4e00-\u9fff]{2,30})\s*[,,]?\s*', '', t) - # 2. 移除@提及: @username - t = re.sub(r'@[A-Za-z0-9_\u4e00-\u9fff]{2,30}\s*', '', t) + # 2. 移除@提及: @username (仅后接空白/串尾时移除,防贪吃无空格的问句) + t = re.sub(r'@[A-Za-z0-9_\u4e00-\u9fff]{2,20}(?=\s|$)', '', t) # 3. 移除时间戳: HH:MM:SS / HH:MM / 日期格式 t = re.sub(r'\d{1,2}[::]\d{2}(?:[::]\d{2})?\s*', '', t) t = re.sub(r'\d{4}[//\-]\d{1,2}[//\-]\d{1,2}\s*', '', t) @@ -360,6 +360,8 @@ def _clean_query_for_kb(msg: str) -> str: t = t.replace(nick, '') except Exception: pass + # 4a. 清理孤立@前缀(昵称移除后@username变成@残余) + t = re.sub(r'^@\s*', '', t) # 5. 清理残留标点/空格 t = re.sub(r'[,,、\s]+', ' ', t).strip(',,、 \t') return t diff --git a/monitor.py b/monitor.py index e4527bb..a9efa2d 100644 --- a/monitor.py +++ b/monitor.py @@ -3819,7 +3819,8 @@ class MessageMonitor: has_q = any(w in line for w in _q_words) # ⭐ 2026-08-11: 规则4剥离")昵称 "前缀的行(如"关于我们")是真实用户消息, # 豁免短句检查——否则规则4放行+前缀剥离全白做,消息仍被此规则丢弃。 - if not has_q and line not in _ui_prefix_stripped: + # ⭐ 2026-08-12: 包含括号的消息(如"端0(基岩版)")可能是有效短消息,放行 + if not has_q and line not in _ui_prefix_stripped and not re.search(r'[()()]', line): logger.debug(f"[{platform}] OCR 过滤: 短句碎片(≤8字无问词) line={line!r}") continue # ★ 以特殊符号(~、`等)开头 → OCR把"一键"识别为"~键"等碎片 @@ -6685,10 +6686,20 @@ class MessageMonitor: # 4a. 全文本签名快速跳过 — OCR 输出与上轮完全相同 → 无变化,跳过 sig = "||".join([t.strip() for t in texts if t.strip()]) if sig == self._last_sig.get(platform, ""): - stale = self._stale_count.get(platform, 0) + 1 - self._stale_count[platform] = stale - logger.debug(f"[{platform}] Poll: 签名相同(#{stale})静默跳过: {sig[:60]!r}") - return + # 检查是否有未回复的消息(防止未回复消息被永久跳过) + unreplied_texts = [t for t in texts if t.strip() and t.strip() not in self._replied_texts] + if not unreplied_texts: + # 所有消息均已回复,正常跳过 + stale = self._stale_count.get(platform, 0) + 1 + self._stale_count[platform] = stale + logger.debug(f"[{platform}] Poll: 签名相同(#{stale})静默跳过: {sig[:60]!r}") + return + else: + # 有未回复消息,继续处理(不跳过) + logger.info(f"[{platform}] Poll: 签名相同但有{len(unreplied_texts)}条未回复消息,继续处理: {[t[:30] for t in unreplied_texts]}") + # 仍然更新 stale 计数器,但不 return + stale = self._stale_count.get(platform, 0) + 1 + self._stale_count[platform] = stale # 4. 用全局 _seen_messages 去重(跨平台、跨轮次防回环) # 精确匹配 + 模糊匹配(OCR 噪声导致精确匹配失效) @@ -6972,7 +6983,9 @@ class MessageMonitor: continue # 模糊匹配:OCR 输出每次微小差异(勖彐碎片、行首数字、尾部截断) # 精确匹配命中不了 → 用 difflib 相似度去重 - if self._fuzzy_duplicate(ts, seen, threshold=0.80): + # ⭐ 2026-08-12: 包含问号的问句(如"PHP用户端有哪两种登录模式?")不视为模糊重复 + # 用户可能重复问相同问题,允许再次处理 + if not re.search(r'[??]', ts) and self._fuzzy_duplicate(ts, seen, threshold=0.80): logger.debug(f"[{platform}] 模糊重复跳过: {ts[:50]}") continue # 超长文本(>200字符)跳过——大概率是堆积历史或 bot 自己的回复,不是单条新消息 diff --git a/monitor_logs.py b/monitor_logs.py new file mode 100644 index 0000000..7e2ae3d --- /dev/null +++ b/monitor_logs.py @@ -0,0 +1,192 @@ +#!/usr/bin/env python3 +""" +实时监控msgbot日志 - 诊断两个问题: +1. 知识库匹配错误(牛头不对马嘴) +2. OCR连续性问题(需要表情包/图片清屏才能触发OCR) + +使用方法: +1. 先启动msgbot +2. 运行此脚本开始监控 +3. 在QQ/微信中发送消息测试 +4. 实时查看分析结果 +""" + +import re +import time +import sys +from collections import defaultdict +from datetime import datetime +from pathlib import Path + +class LogAnalyzer: + def __init__(self): + self.kb_matches = [] + self.ocr_events = [] + self.pixel_stats = [] + self.replies = [] + + def analyze_line(self, line: str): + """分析单行日志""" + line = line.strip() + if not line: + return + + # 分析KB匹配 + if "KB搜索输入" in line: + self.kb_matches.append({ + 'time': datetime.now(), + 'type': 'search_input', + 'content': line + }) + + # 分析KB结果 + elif "KB结果" in line and "标题" in line: + self.kb_matches.append({ + 'time': datetime.now(), + 'type': 'search_result', + 'content': line + }) + + # 分析内容相关性 + elif "内容相关性检查" in line: + self.kb_matches.append({ + 'time': datetime.now(), + 'type': 'relevance_check', + 'content': line + }) + + # 分析像素检测 + elif "像素统计" in line or "像素检测" in line: + self.pixel_stats.append({ + 'time': datetime.now(), + 'content': line + }) + + # 分析OCR事件 + elif "OCR" in line and ("跳过" in line or "触发" in line or "输出" in line): + self.ocr_events.append({ + 'time': datetime.now(), + 'content': line + }) + + # 分析回复 + elif "新消息" in line and ("回复" in line or "发送" in line): + self.replies.append({ + 'time': datetime.now(), + 'content': line + }) + + def print_summary(self): + """打印分析摘要""" + print("\n" + "="*80) + print(f"分析摘要 - {datetime.now().strftime('%H:%M:%S')}") + print("="*80) + + # KB匹配分析 + print(f"\n【知识库匹配】共 {len(self.kb_matches)} 条记录") + if self.kb_matches: + print(" 最近5条:") + for item in self.kb_matches[-5:]: + print(f" [{item['time'].strftime('%H:%M:%S')}] {item['content'][:80]}") + + # 像素检测分析 + print(f"\n【像素检测】共 {len(self.pixel_stats)} 条记录") + if self.pixel_stats: + print(" 最近5条:") + for item in self.pixel_stats[-5:]: + print(f" [{item['time'].strftime('%H:%M:%S')}] {item['content'][:80]}") + + # OCR事件分析 + print(f"\n【OCR事件】共 {len(self.ocr_events)} 条记录") + if self.ocr_events: + print(" 最近5条:") + for item in self.ocr_events[-5:]: + print(f" [{item['time'].strftime('%H:%M:%S')}] {item['content'][:80]}") + + # 回复分析 + print(f"\n【回复记录】共 {len(self.replies)} 条记录") + if self.replies: + print(" 最近5条:") + for item in self.replies[-5:]: + print(f" [{item['time'].strftime('%H:%M:%S')}] {item['content'][:80]}") + + print("="*80) + +def monitor_log_file(log_file: str): + """监控日志文件""" + print(f"开始监控日志文件: {log_file}") + print("按 Ctrl+C 停止监控") + print("-"*80) + + analyzer = LogAnalyzer() + + try: + with open(log_file, 'r', encoding='utf-8', errors='ignore') as f: + # 跳到文件末尾 + f.seek(0, 2) + + while True: + line = f.readline() + if not line: + time.sleep(0.1) + continue + + analyzer.analyze_line(line) + print(line.rstrip()) + + # 每30秒打印一次摘要 + if int(time.time()) % 30 == 0: + analyzer.print_summary() + + except KeyboardInterrupt: + print("\n监控已停止") + analyzer.print_summary() + except FileNotFoundError: + print(f"日志文件不存在: {log_file}") + print("请先启动msgbot,然后运行此脚本") + +def main(): + """主函数""" + # 查找最新的日志文件 + log_patterns = [ + "msgbot.log", + "monitor.log", + "debug.log", + "*.log" + ] + + log_files = [] + for pattern in log_patterns: + log_files.extend(list(Path(".").glob(pattern))) + + if not log_files: + print("未找到日志文件,请先启动msgbot") + print("然后运行此脚本开始监控") + return + + print("找到以下日志文件:") + for i, f in enumerate(log_files, 1): + print(f" {i}. {f.name}") + + print("\n监控功能说明:") + print("1. 实时显示日志内容") + print("2. 自动分析KB匹配过程") + print("3. 跟踪像素检测结果") + print("4. 记录OCR事件") + print("5. 监控回复发送") + + # 选择要监控的文件 + if len(log_files) == 1: + monitor_log_file(str(log_files[0])) + else: + try: + choice = int(input("\n请选择要监控的日志文件编号: ")) - 1 + if 0 <= choice < len(log_files): + monitor_log_file(str(log_files[choice])) + else: + print("无效的选择") + except ValueError: + print("请输入有效的数字") + +if __name__ == "__main__": + main() \ No newline at end of file