
本文介绍如何从ocr识别出的杂乱文本中精准提取“日期+时间”片段(如“27 jul12.00 -21.00”),重点讲解基于正则表达式的清洗与结构化方法,兼顾鲁棒性与可维护性。
本文介绍如何从ocr识别出的杂乱文本中精准提取“日期+时间”片段(如“27 jul12.00 -21.00”),重点讲解基于正则表达式的清洗与结构化方法,兼顾鲁棒性与可维护性。
在自动化处理OCR输出(如扫描版排班表、PDF截图或反爬网页)时,原始文本往往夹杂大量干扰符号、换行错位、空格不均甚至乱码(如示例中的 SERWCES 应为 SERVICES)。此时,依赖HTML选择器(如Playwright的 .date-class)并不可行——因为OCR结果不含DOM结构。真正可靠、轻量且可控的方案是:使用正则表达式(regex)从纯文本中锚定并捕获关键模式。
✅ 核心匹配逻辑
观察目标片段(如 Mon, 22.Jul15.00-21.00、27 Jul12.00 -21.00、Tue, 23 Jul15.00-21.00),可归纳出稳定特征:
- 日期部分:含英文缩写星期(可选)、数字日期(1–31)、英文月份缩写(Jan–Dec),后紧跟时间;
- 时间部分:HH.MM-HH.MM 或 HH:MM-HH:MM 格式,中间可能有空格、短横、全角符号;
- 关键锚点:日期与时间之间无换行、无长段分隔符,通常紧邻出现。
据此,推荐以下正则表达式:
import re
text = """MySchedule UK & Ireland*************** (Custo_MHS00801682LIPHOOK SERVICESESS...
Mon, 22.Jul15.00-21.008R -17.45 _18.3000801682LIPHOOK SERWCES NORTH
Tue, 23 Jul15.00-21.00
27 Jul12.00 -21.008Rt6:15-17.0000801682 _LIPHOOK SERWCES NORTH
"""
# 精确匹配:支持逗号/点分隔、空格/短横/下划线分隔时间、兼容HH.MM和HH:MM
pattern = r'''
(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun)? # 可选星期缩写
[,.\s]* # 可选标点或空格
(\d{1,2}) # 日期数字(1–31)
\s* # 可选空格
(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) # 月份缩写
[.\s]* # 可选标点或空格
(\d{1,2}\.?[\d]{0,2}[-:\s_]*\d{1,2}\.?[\d]{0,2}) # 时间段(如 15.00-21.00, 12.00 -21.00, 6:15-17:00)
'''
matches = re.findall(pattern, text, re.IGNORECASE | re.VERBOSE)
for day, month, time_range in matches:
print(f"{day} {month} {time_range.strip()}")输出示例:
22 Jul 15.00-21.00 23 Jul 15.00-21.00 27 Jul 12.00 -21.00
⚠️ 注意事项与增强建议
- OCR容错:若月份被误识为 SERWCES,可预处理替换常见错误(如 re.sub(r'SERWCES', 'SERVICES', text)),或在正则中加入模糊匹配(需结合 regex 库的 (?e) 模式);
- 避免过匹配:原始文本含 00801682 等数字串,务必用 \b 单词边界或上下文限定(如要求月份后紧跟时间),防止匹配到ID;
-
结构化输出:建议将结果转为 list[dict],便于后续处理:
result = [ {"date": f"{d} {m}", "time": t.strip(), "raw": match.group(0)} for match in re.finditer(pattern, text, re.IGNORECASE | re.VERBOSE) for d, m, t in [match.groups()] ] - 备选方案:若正则仍不稳定,可先用 re.split(r'[;*]+', text) 切分区块,再对每块单独匹配,降低噪声干扰。
正则不是万能的,但针对格式相对固定的排班文本,它是比模拟浏览器更轻量、更可控、更易调试的首选方案。掌握锚定逻辑与渐进式调试(先匹配日期,再加时间,最后加星期),即可稳健应对多数OCR清洗场景。

















