通过 python-docx 这个强大的库,我们可以读取文档的结构、文本内容以及格式信息(如高亮、颜色等),从而实现将试卷和答案分离的目标。
这个任务的核心是确定一个可靠的规则来区分“题目”和“答案”。您提到的“标注文本”是关键。在Word中,常见的标注方法有:
高亮颜色 (Highlight Color):给答案文本设置一个背景色(如黄色)。
字体颜色 (Font Color):将答案文本的颜色设置为不同于题目的颜色(如红色)。
特定标记 (Keywords):在答案前后使用固定的关键词,如 【答案】 或 (Answer)。
下面我将提供两种最常用、最可靠的方案(基于高亮和字体颜色),并附上完整的Python代码。
准备工作
首先,你需要安装 python-docx 库。
pip install python-docx
然后,准备一个Word文档作为示例,我们命名为 sample_paper.docx。在这个文档里,我们用高亮或者红色字体来标记答案。
方案一:根据“高亮颜色”分离
这是最推荐的方法,因为它通常不会与题目本身的格式(如加粗、斜体)冲突。
逻辑思路:
遍历文档中的每一个段落(Paragraph)。
在每个段落中,遍历每一个文本块(Run)。一个“Run”是具有相同格式的连续文本。
检查每个Run是否有高亮颜色。
创建两个新的Word文档:一个用于试卷,一个用于答案。
将非高亮的Run(题目部分)同时写入试卷和答案文档。
将高亮的Run(答案部分)只写入答案文档。对于试卷文档,可以在对应位置留空或添加下划线 (____)。
Python代码实现:
from docx import Document
from docx.enum.text import WD_COLOR_INDEX
def copy_run_format(source_run, target_run):
"""复制一个Run的格式(字体、大小、加粗、斜体等)"""
target_run.bold = source_run.bold
target_run.italic = source_run.italic
target_run.underline = source_run.underline
target_run.font.name = source_run.font.name
target_run.font.size = source_run.font.size
target_run.font.color.rgb = source_run.font.color.rgb
def separate_by_highlight(source_path, paper_path, key_path):
"""
根据高亮颜色分离试卷和答案。
- source_path: 原始Word文档路径
- paper_path: 生成的试卷文件路径
- key_path: 生成的答案文件路径
"""
source_doc = Document(source_path)
paper_doc = Document()
key_doc = Document()
print(f"开始处理文档: {source_path}")
for para in source_doc.paragraphs:
# 为两个新文档创建新段落
paper_p = paper_doc.add_paragraph()
key_p = key_doc.add_paragraph()
# 复制原段落的格式(如对齐方式)
paper_p.paragraph_format.alignment = para.paragraph_format.alignment
key_p.paragraph_format.alignment = para.paragraph_format.alignment
# 标记当前段落是否包含答案
has_answer_in_para = any(
run.font.highlight_color is not None and run.font.highlight_color != WD_COLOR_INDEX.AUTO
for run in para.runs
)
for run in para.runs:
# 检查当前run是否是高亮(答案)
is_answer = run.font.highlight_color is not None and run.font.highlight_color != WD_COLOR_INDEX.AUTO
if is_answer:
# 如果是答案,则只写入答案文档,并保留其原始格式
key_run = key_p.add_run(run.text)
copy_run_format(run, key_run)
# 答案部分也恢复正常背景色
key_run.font.highlight_color = WD_COLOR_INDEX.AUTO
else:
# 如果是题目,则同时写入试卷和答案文档
paper_run = paper_p.add_run(run.text)
copy_run_format(run, paper_run)
key_run = key_p.add_run(run.text)
copy_run_format(run, key_run)
# 如果段落中包含答案,在试卷的相应段落末尾添加括号用于填写
if has_answer_in_para:
paper_p.add_run(" (____)")
paper_doc.save(paper_path)
key_doc.save(key_path)
print(f"处理完成!\n试卷已保存至: {paper_path}\n答案已保存至: {key_path}")
# --- 使用示例 ---
if __name__ == "__main__":
# 假设你的Word文档叫 sample_paper.docx,并且答案用高亮标记
source_file = 'sample_paper.docx'
output_paper_file = 'generated_paper.docx'
output_key_file = 'generated_key.docx'
separate_by_highlight(source_file, output_paper_file, output_key_file)方案二:根据“字体颜色”分离
如果你的答案是用特定颜色(如红色)标记的,原理类似。
逻辑思路:与方案一基本相同,只是判断条件从 run.font.highlight_color 变为 run.font.color.rgb。
Python代码实现:
from docx import Document
from docx.shared import RGBColor
# copy_run_format 函数同上,这里省略
def separate_by_font_color(source_path, paper_path, key_path, answer_color=RGBColor(255, 0, 0)):
"""
根据字体颜色分离试卷和答案。
- answer_color: 用于标记答案的RGB颜色,默认为红色。
"""
source_doc = Document(source_path)
paper_doc = Document()
key_doc = Document()
print(f"开始处理文档: {source_path}")
for para in source_doc.paragraphs:
paper_p = paper_doc.add_paragraph()
key_p = key_doc.add_paragraph()
paper_p.paragraph_format.alignment = para.paragraph_format.alignment
key_p.paragraph_format.alignment = para.paragraph_format.alignment
has_answer_in_para = any(
run.font.color.rgb == answer_color for run in para.runs
)
for run in para.runs:
# 检查当前run的颜色是否是答案颜色
is_answer = run.font.color.rgb == answer_color
if is_answer:
key_run = key_p.add_run(run.text)
copy_run_format(run, key_run)
# 将答案的颜色恢复为黑色
key_run.font.color.rgb = RGBColor(0, 0, 0)
else:
paper_run = paper_p.add_run(run.text)
copy_run_format(run, paper_run)
key_run = key_p.add_run(run.text)
copy_run_format(run, key_run)
if has_answer_in_para:
paper_p.add_run(" (____)")
paper_doc.save(paper_path)
key_doc.save(key_path)
print(f"处理完成!\n试卷已保存至: {paper_path}\n答案已保存至: {key_path}")
# --- 使用示例 ---
if __name__ == "__main__":
# 假设你的Word文档叫 sample_paper.docx,并且答案用红色字体标记
# from docx.shared import RGBColor
# copy_run_format 函数需要放在这里或全局
source_file = 'sample_paper.docx'
output_paper_file = 'generated_paper_by_color.docx'
output_key_file = 'generated_key_by_color.docx'
# 假设答案是红色 (R:255, G:0, B:0)
separate_by_font_color(source_file, output_paper_file, output_key_file, answer_color=RGBColor(255, 0, 0)) 重要提示和扩展
复杂文档:以上代码处理的是纯文本段落。如果你的Word文档中包含表格(Table)、图片(Image)或复杂的列表格式,代码需要进行扩展来处理这些元素。例如,你需要遍历表格中的单元格(cell)并对其中的段落应用相同的逻辑。
格式保持:copy_run_format 函数是为了尽可能多地保留原始格式。你可以根据需要添加更多格式的复制,例如字体效果(阴影、轮廓等)。
灵活性:你可以将这两个函数合并,通过一个 method 参数(如 'highlight' 或 'color')来选择使用哪种分离方式,使代码更具通用性。
网友回复
有没有免费让ai自动帮你接管操作电脑的mcp服务?
mcp为啥用Streamable HTTP 替代 HTTP + SSE?
scratchjr有没有开源的前端html网页版本源代码?
多模态大模型能否根据ui交互视频来来模仿写出前端交互动画效果ui代码?
如何用阿里云oss+函数计算fc+事件总线EventBridge+消息队列+数据库+redis缓存打造一个高并发弹性系统?
阿里云函数计算 FC如何在海外节点搭建一个代理网络?
ai studio中gemini build的代码如何发布到github pages等免费网页托管上 ?
如何在cursor、qoder、trae中使用Claude Skills功能?
有没有不用u盘就能重装系统的开源工具?
python如何固定摄像头实时计算停车场停车位剩余数量?


