OCR截屏JSON/YAML配置块剥离:新增_strip_json_yaml_blocks方法在切行前剥离JSON对象块/key-value行/YAML列表;OCR行过滤和Poll过滤加JSON/YAML语法兜底;修复微信右侧配置面板与用户消息搅合导致消息丢失

This commit is contained in:
youpaishidifu
2026-07-28 18:58:54 +08:00
parent f3cdb142b8
commit 94cf619f3d
+90
View File
@@ -1121,6 +1121,12 @@ class MessageMonitor:
self._ocr_garbage_count[platform] = 0 self._ocr_garbage_count[platform] = 0
self._ocr_last_text[platform] = raw_text self._ocr_last_text[platform] = raw_text
# —— JSON/YAML 配置块剥离 ——
# 微信 OCR 截屏范围 40%-98%,常把右侧文档/配置面板(JSON/YAML)一起截入
# JSON 块("key": value, {, })和 YAML 块(key: value)跟用户消息混在一起
# 在 split 前先剥离这些行,避免 JSON 碎片污染用户消息
raw_text = self._strip_json_yaml_blocks(raw_text, platform)
# —— 行切割 + 尾标清理 —— # —— 行切割 + 尾标清理 ——
ocr_lines = [] ocr_lines = []
for l in raw_text.split('\n'): for l in raw_text.split('\n'):
@@ -1309,6 +1315,17 @@ class MessageMonitor:
logger.debug(f"[{platform}] OCR 过滤: 纯非中文乱码 line={line!r}") logger.debug(f"[{platform}] OCR 过滤: 纯非中文乱码 line={line!r}")
continue continue
# —— JSON/YAML 碎片兜底:OCR 截屏混入配置面板 ——
# 行首是 "key": value 或 key: value(YAML)→ 配置面板碎片
if re.match(r'^["\']?[a-zA-Z_][\w]*["\']?\s*:\s*["\d\[\{tfn]', line):
logger.debug(f"[{platform}] OCR 过滤: JSON行 {line!r}")
continue
if re.match(r'^[a-zA-Z_][\w]*\s*:\s*["\w\d]', line) and \
not re.match(r'^(https?|ftp)://', line) and \
not re.match(r'^[a-zA-Z_][\w]*\s*:\s*/', line):
logger.debug(f"[{platform}] OCR 过滤: YAML行 {line!r}")
continue
# —— 末尾 #标题 碎片兜底 —— # —— 末尾 #标题 碎片兜底 ——
# OCR 时间戳分割可能遗漏尾部 " #测试" " #草" 等 md 标题碎片 # OCR 时间戳分割可能遗漏尾部 " #测试" " #草" 等 md 标题碎片
# 注:\s+ 要求空格在前,避免误杀 "C#语言" "中文#标签" # 注:\s+ 要求空格在前,避免误杀 "C#语言" "中文#标签"
@@ -1724,6 +1741,70 @@ class MessageMonitor:
return True return True
return False return False
@staticmethod
def _strip_json_yaml_blocks(raw_text: str, platform: str = "") -> str:
"""剥离 OCR 截屏中混入的 JSON/YAML 配置块。
微信 OCR 截屏范围 40%-98%,常把右侧文档/配置面板一起截入。
JSON 块("key": value, {, })和 YAML 块(key: value, - item)
跟用户消息混在一起,导致 split 后 JSON 碎片污染用户消息行。
策略:逐行检测,丢弃明显是 JSON/YAML 语法的行。
用户聊天不会写 "key": value 或 { } 块。
"""
lines = raw_text.split('\n')
cleaned = []
in_json_block = False
brace_depth = 0
for line in lines:
stripped = line.strip()
if not stripped:
cleaned.append(line)
continue
# 检测 JSON 对象块开始/结束
if stripped == '{' or stripped.startswith('{') and '"' in stripped:
in_json_block = True
brace_depth = stripped.count('{') - stripped.count('}')
logger.debug(f"[{platform}] JSON块剥离: 开始 {stripped[:60]!r}")
continue
if in_json_block:
brace_depth += stripped.count('{') - stripped.count('}')
if brace_depth <= 0:
in_json_block = False
logger.debug(f"[{platform}] JSON块剥离: 结束 {stripped[:60]!r}")
continue
# JSON 行特征: "key": value 或 "key": "value"
if re.match(r'^["\']?[a-zA-Z_][\w]*["\']?\s*:\s*["\d\[\{tfn]', stripped):
logger.debug(f"[{platform}] JSON块剥离: key-value行 {stripped[:60]!r}")
continue
# YAML 行特征: key: value(无引号,非 URL)
if re.match(r'^[a-zA-Z_][\w]*\s*:\s*["\w\d]', stripped) and \
not re.match(r'^(https?|ftp)://', stripped) and \
not re.match(r'^[a-zA-Z_][\w]*\s*:\s*/', stripped):
logger.debug(f"[{platform}] JSON块剥离: YAML行 {stripped[:60]!r}")
continue
# YAML 列表项: - item
if re.match(r'^-\s+\S', stripped) and \
not re.match(r'^-\s*[\u4e00-\u9fff]', stripped):
logger.debug(f"[{platform}] JSON块剥离: YAML列表 {stripped[:60]!r}")
continue
# 纯 JSON 数组: [ "item", ... ]
if stripped.startswith('[') and stripped.endswith(']') and \
'"' in stripped:
logger.debug(f"[{platform}] JSON块剥离: 数组 {stripped[:60]!r}")
continue
cleaned.append(line)
return '\n'.join(cleaned)
@staticmethod @staticmethod
def _is_markdown_document(text: str) -> bool: def _is_markdown_document(text: str) -> bool:
"""检测是否为 Markdown 格式的文档内容。 """检测是否为 Markdown 格式的文档内容。
@@ -2471,6 +2552,15 @@ class MessageMonitor:
if not re.search(r'[\u4e00-\u9fff]', ts) and len(ts) > 15 and not ts.startswith('/'): if not re.search(r'[\u4e00-\u9fff]', ts) and len(ts) > 15 and not ts.startswith('/'):
logger.debug(f"[{platform}] Poll过滤: 无中文乱码 ts={ts!r}") logger.debug(f"[{platform}] Poll过滤: 无中文乱码 ts={ts!r}")
continue continue
# === JSON/YAML 碎片兜底:OCR 截屏混入配置面板 ===
if re.match(r'^["\']?[a-zA-Z_][\w]*["\']?\s*:\s*["\d\[\{tfn]', ts):
logger.debug(f"[{platform}] Poll过滤: JSON行 ts={ts!r}")
continue
if re.match(r'^[a-zA-Z_][\w]*\s*:\s*["\w\d]', ts) and \
not re.match(r'^(https?|ftp)://', ts) and \
not re.match(r'^[a-zA-Z_][\w]*\s*:\s*/', ts):
logger.debug(f"[{platform}] Poll过滤: YAML行 ts={ts!r}")
continue
# === 安全阀:UI 子串过滤(兜底,防任何路径漏过)=== # === 安全阀:UI 子串过滤(兜底,防任何路径漏过)===
if any(sub in ts for sub in _UI_SUBSTR_BLOCKLIST): if any(sub in ts for sub in _UI_SUBSTR_BLOCKLIST):
logger.debug(f"[{platform}] Poll过滤: UI子串 ts={ts!r}") logger.debug(f"[{platform}] Poll过滤: UI子串 ts={ts!r}")