From 2162a490683cfe8607cdbe7f51c7ecde788f9e09 Mon Sep 17 00:00:00 2001 From: youpaishidifu Date: Mon, 3 Aug 2026 15:20:28 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E6=98=A8=E5=A4=A9=E7=9A=84=E6=97=B6?= =?UTF-8?q?=E9=97=B4=E6=88=B3=E4=B8=8D=E5=86=8D=E8=A2=AB=E8=AF=AF=E5=88=A4?= =?UTF-8?q?=E4=B8=BA=E4=BB=8A=E5=A4=A9=E6=9C=AA=E6=9D=A5=E7=9A=8421:14?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在_ocr_text_has_fresh_timestamp中提取日期信息(如2026/8/2) - 如果日期是过去的(昨天或更早),跳过未来时间戳拦截 - 修改_is_timestamp_old函数,添加skip_future_check参数 - 解决问题:OCR文本包含2026/8/2 21:14:38,被误判为今天未来的21:14 --- monitor.py | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 2 deletions(-) diff --git a/monitor.py b/monitor.py index 7c6247e..4ddac68 100644 --- a/monitor.py +++ b/monitor.py @@ -3390,6 +3390,31 @@ class MessageMonitor: normalized = re.sub(r'(\d{1,2})[.;](\d{2})(?:[.;](\d{2}))?', r'\1:\2:\3', text) timestamps = re.findall(r'\d{1,2}:\d{1,2}(?::\d{1,2})?', normalized) logger.debug(f"[ocr] 提取到时间戳: {timestamps}") + + # 提取日期信息(如2026/8/2、2026-08-02等),用于判断时间戳是否真的是"未来" + dates = re.findall(r'\d{4}[/-]\d{1,2}[/-]\d{1,2}', text) + # 标准化日期分隔符 + dates = [d.replace('-', '/') for d in dates] + logger.debug(f"[ocr] 提取到日期: {dates}") + + # 计算日期差:如果是过去的日期(昨天或更早),时间戳不应该是"未来时间戳" + has_past_date = False + if dates: + today = datetime.now().date() + for date_str in dates: + try: + # 解析日期:2026/8/2 或 2026/08/02 + parts = date_str.split('/') + if len(parts) == 3: + y, m, d = int(parts[0]), int(parts[1]), int(parts[2]) + date_obj = datetime(y, m, d).date() + date_diff = (today - date_obj).days + if date_diff > 0: # 昨天或更早 + has_past_date = True + logger.debug(f"[ocr] 检测到过去日期: {date_str} (距今{date_diff}天)") + break + except (ValueError, IndexError): + pass if not timestamps: # ⭐ 无可见时间戳:仅超短中文消息(如"好的""嗯")视为可能的新消息放行; # 较长文本无时间戳 → 无法验证新鲜性,可能是不含时间戳的历史/UI噪声 @@ -3418,6 +3443,36 @@ class MessageMonitor: return False logger.debug(f"[ocr] 过滤器1结果: 无时间戳且非超短消息,丢弃: {text[:80]!r}") return False + # 如果检测到过去日期(昨天或更早),时间戳不应该是"未来时间戳" + # 直接放行,让后续逻辑判断是否过期 + if has_past_date: + logger.debug(f"[ocr] 检测到过去日期,跳过未来时间戳拦截,直接判断是否过期") + # 检查是否有新鲜时间戳(≤300s) + for ts in timestamps: + try: + if not self._is_timestamp_old(ts, 300, skip_future_check=True): + logger.debug(f"[ocr] 过滤器1结果: 过去日期+新鲜时间戳{ts}(≤300s),放行") + return True + except Exception: + pass + # 检查最新时间戳是否在300-600s之间 + newest_fresh_enough = False + for ts in timestamps: + try: + if not self._is_timestamp_old(ts, 600, skip_future_check=True): + newest_fresh_enough = True + break + except Exception: + pass + if not newest_fresh_enough: + logger.debug(f"[ocr] 过滤器1结果: 过去日期+最新时间戳已过期≥600s,丢弃: {text[:80]!r}") + return False + # 最新时间戳在 300-600s 之间,且文本含明确新鲜特征 → 放行 + if self._looks_fresh_content(text): + logger.debug(f"[ocr] 过滤器1结果: 过去日期+时间戳全过期但最新≤600s且含新鲜特征,放行: {text[:80]!r}") + return True + logger.debug(f"[ocr] 过滤器1结果: 过去日期+时间戳全过期且无新鲜特征,丢弃: {text[:80]!r}") + return False # 有新鲜时间戳 → 确定有新消息 for ts in timestamps: try: @@ -3451,13 +3506,15 @@ class MessageMonitor: _TS_FUTURE_TOLERANCE_S = 15 @staticmethod - def _is_timestamp_old(ts_str: str, max_age: int = 300) -> bool: + def _is_timestamp_old(ts_str: str, max_age: int = 300, skip_future_check: bool = False) -> bool: """检查 HH:MM 或 HH:MM:SS 时间戳是否超过 max_age 秒。 处理跨午夜边界:如果 diff > 12h 说明是昨天的时间戳。 未来时间戳硬拦截:同日内 diff < -容差 = 时间未到来(系统14:40不可能有16:00),丢弃。 OCR 误读兜底:15:31→5:31(`1`笔画细被吞),若 h<12,尝试 h+10/h+12 取 diff 最小者,若 < max_age 则视为 OCR 误读,放行。 返回 True = 时间戳太老,应跳过。 + + skip_future_check: 如果为True,则跳过未来时间戳拦截(用于已检测到过去日期的情况)。 """ ts = ts_str.strip() if not ts: @@ -3487,7 +3544,8 @@ class MessageMonitor: diff = (now - parsed).total_seconds() # 未来时间戳硬拦截(用户反馈:系统14:40 不能把 16:00 未到来的时间判为新鲜): # 跨午夜调整后仍为负 = 同日内未来时间,必为 OCR 误读/异常,直接丢弃 - if diff < -MessageMonitor._TS_FUTURE_TOLERANCE_S: + # skip_future_check=True 时跳过此检查(用于已检测到过去日期的情况) + if diff < -MessageMonitor._TS_FUTURE_TOLERANCE_S and not skip_future_check: logger.debug(f"[ts] 未来时间戳拦截: {ts} 比系统时间 {now.strftime('%H:%M:%S')} 晚 {-diff:.0f}s,未到来,丢弃") return True # OCR 误读兜底:h<12 且判定为老 → 尝试 h+10 / h+12(OCR 丢失前导1:15→5)