You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python中如何使用正则表达式提取考题文本结构化字段

Python正则提取考题字段最优实现

不要写单条超长正则硬匹配全字段,这是这类结构化文本提取最容易踩的坑——只要文本里多一个换行、一个HTML标签、一个多余空格,整条正则就直接失效,后续改规则也极其麻烦。最优实现是先预处理清格式、再按锚点切分单题、最后逐字段匹配,容错率和可维护性比单条正则高几个量级。

具体实现逻辑

  1. 文本预处理:先把所有HTML标签(比如示例里的<p>、<a>)、连续换行/制表符/多余空格统一替换成单个空格,抹平格式差异,避免无关格式干扰匹配。
  2. 切分单题块:以QUESTION NO:作为分割锚点,把整段长文本拆成独立的单道题目片段,从根源上避免跨题匹配的问题。
  3. 对每个单题块,用针对性的短正则分别提取目标字段:
    • 题号:匹配QUESTION NO:后的数字,正则为r'QUESTION NO:\s*(\d+)'
    • 题干文本:匹配题号结束后、第一个选项(A./B.这类大写字母加句号开头的内容)之前的所有文本,正则用r'QUESTION NO:\s*\d+\s*(.*?)\s*(?=[A-Z]\.)',开非贪婪模式,匹配到第一个选项就停止
    • 可选答案:匹配所有选项ID开头的片段,正则为r'([A-Z])\.\s*(.*?)\s*(?=[A-Z]\.|Answer:)',匹配结果直接组装成{选项ID:选项内容}的字典
    • 正确答案:匹配Answer:后、Explanation:前的内容,正则为r'Answer:\s*([A-Z,\s]+)\s*(?=Explanation:)',拿到结果后按逗号分割就能得到正确答案列表
    • 答案解析:匹配Explanation:后的所有剩余内容,正则为r'Explanation:\s*(.*)$'

可直接复用的代码

import re
from typing import List, Dict

def extract_exam_questions(raw_text: str) -> List[Dict]:
    # 清理HTML标签
    clean_content = re.sub(r'<[^>]+>', '', raw_text)
    # 合并所有多余空白字符
    clean_content = re.sub(r'\s+', ' ', clean_content).strip()
    # 按题号锚点切分单题
    question_units = re.split(r'(?=QUESTION NO:\s*\d+)', clean_content)
    exam_result = []
    for unit in question_units:
        if not unit.strip():
            continue
        # 提取题号
        qid_match = re.search(r'QUESTION NO:\s*(\d+)', unit)
        question_id = qid_match.group(1) if qid_match else ''
        # 提取题干
        stem_match = re.search(r'QUESTION NO:\s*\d+\s*(.*?)\s*(?=[A-Z]\.)', unit)
        question_stem = stem_match.group(1).strip() if stem_match else ''
        # 提取所有选项
        options = {}
        for opt in re.finditer(r'([A-Z])\.\s*(.*?)\s*(?=[A-Z]\.|Answer:)', unit):
            opt_id, opt_text = opt.groups()
            options[opt_id] = opt_text.strip()
        # 提取正确答案
        ans_match = re.search(r'Answer:\s*([A-Z,\s]+)\s*(?=Explanation:)', unit)
        correct_answers = [a.strip() for a in ans_match.group(1).split(',')] if ans_match else []
        # 提取解析
        exp_match = re.search(r'Explanation:\s*(.*)$', unit)
        explanation = exp_match.group(1).strip() if exp_match else ''
        exam_result.append({
            "题号": question_id,
            "题干文本": question_stem,
            "可选答案": options,
            "正确答案": correct_answers,
            "答案解析": explanation
        })
    return exam_result

# 调用示例
if __name__ == "__main__":
    # 替换为你的待处理原始文本即可
    raw_text = """此处传入待处理的考题原始文本"""
    all_questions = extract_exam_questions(raw_text)
    for q in all_questions:
        print(q)

之前尝试的正则失效原因

你之前写的(?:QUESTION NO: )(\d+)(\w+)失效核心原因有两个:

  • \w+只能匹配连续的字母、数字、下划线,题干开头的空格、括号、特殊标点都无法匹配
  • 没有加非贪婪匹配和边界断言,匹配逻辑会无限制向后吞文本,直接打乱后续的题号匹配规则

内容的提问来源于stack exchange,提问作者Adam Chubbuck

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 11:48:25