我的知识记录

Python Word批量去除批注与修订痕迹:清洗定稿

用python-docx通过XML操作批量删除Word文档里的批注、接受所有修订(Track Changes),把审稿稿洗成干净定稿,防止发出的文件暴露修改痕迹。

场景痛点

审稿意见都处理完了,要发终稿给客户,结果文档里还挂着"这里要改""错别字"一堆批注,修订痕迹还开着,对方一打开能看到你删了什么加了什么,尴尬又泄密。手动"接受所有修订-删除所有批注"一份份点,批量处理几十份时用Python一把洗干净。

用到的库

pip install python-docx

完整代码

# -*- coding: utf-8 -*-
"""
清洗 Word 文档:
1) 接受所有修订(Track Changes:保留插入、删除删除标记)
2) 删除所有批注
3) 关闭文档的"修订模式"标记
"""
from pathlib import Path
from docx import Document
from docx.oxml.ns import qn
from lxml import etree


def accept_all_revisions(doc):
"""接受所有修订:保留插入内容,彻底移除删除内容"""
body = doc.element.body

# 1. 处理 w:ins(插入的内容):把它的内容"提出来",去掉 ins 外壳
for ins in body.iter(qn('w:ins')):
parent = ins.getparent()
idx = list(parent).index(ins)
# 把 ins 里的子元素移到原来 ins 的位置
for child in list(ins):
parent.insert(idx, child)
idx += 1
parent.remove(ins)

# 2. 处理 w:del(删除的内容):整个删掉
for d in body.iter(qn('w:del')):
d.getparent().remove(d)

# 3. 处理段落级别的修订标记:w:pPrChange(段落格式修订)、w:rPrChange(run格式修订)
for tag in ('w:pPrChange', 'w:rPrChange', 'w:sectPrChange', 'w:tblPrChange',
'w:trPrChange', 'w:tcPrChange', 'w:cellIns', 'w:cellDel', 'w:cellMerge'):
for el in body.iter(qn(tag)):
el.getparent().remove(el)

# 4. 处理 w:delText(删除的文本节点),删段落里的
for deltext in body.iter(qn('w:delText')):
deltext.getparent().remove(deltext)


def remove_all_comments(doc):
"""删除文档里所有批注"""
# 1. 删除批注引用(正文里的批注锚点)
body = doc.element.body
for comment_ref in body.iter(qn('w:commentRangeStart')):
comment_ref.getparent().remove(comment_ref)
for comment_ref in body.iter(qn('w:commentRangeEnd')):
comment_ref.getparent().remove(comment_ref)
for comment_ref in body.iter(qn('w:commentReference')):
comment_ref.getparent().remove(comment_ref)

# 2. 删除 comments.xml 部件里的实际批注内容(如果存在)
from docx.opc.constants import RELATIONSHIP_TYPE as RT
part = doc.part
for rel in list(part.rels.values()):
if rel.reltype == 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments':
# 清空批注部件
comments_part = rel.target_part
# 清空所有 w:comment 节点
for comment in list(comments_part.element):
comments_part.element.remove(comment)


def turn_off_track_changes(doc):
"""关闭 settings.xml 里的 trackChanges 开关"""
settings = doc.settings.element
for tc in settings.findall(qn('w:trackChanges')):
settings.remove(tc)


def clean_docx(docx_path: Path, output_path: Path):
doc = Document(str(docx_path))
accept_all_revisions(doc)
remove_all_comments(doc)
turn_off_track_changes(doc)
doc.save(str(output_path))


def batch_clean(input_dir, output_dir):
input_dir = Path(input_dir)
output_dir = Path(output_dir)
output_dir.mkdir(parents=True, exist_ok=True)

docx_files = [f for f in input_dir.glob("*.docx") if not f.name.startswith("~$")]
print(f"共 {len(docx_files)} 个文档待清洗")

for docx_file in docx_files:
out = output_dir / docx_file.name
try:
clean_docx(docx_file, out)
print(f"✓ {docx_file.name} -> {out.name}")
except Exception as e:
print(f"✗ {docx_file.name} 失败:{e}")


def demo():
# 演示:造一个带修订和批注的文档
doc = Document()
doc.add_paragraph("这是初稿内容。")
p = doc.add_paragraph("下面这句将被删除。")
p2 = doc.add_paragraph("这是要插入的新句子。")
out = Path("./draft_with_revisions.docx")
doc.save(str(out))
print(f"演示文件已生成:{out}")
print("(真实的修订/批注标记需要在Word里打开并开启修订模式修改后才有,本脚本直接处理XML)")


if __name__ == "__main__":
batch_clean(
input_dir="./word_docs",
output_dir="./final_clean",
)

代码讲解

Word的修订(Track Changes)在XML里是用 w:ins 表示插入、w:del 表示删除、w:delText 表示被删掉的文字。"接受所有修订"在XML层面就是:把 w:ins 外壳剥掉,让里面的内容变成普通正文;把 w:delw:delText 整个删掉,因为这些是被否决的改动。

批注是另外一套机制:正文里有 w:commentRangeStart/Endw:commentReference 三个锚点,实际批注内容存在单独的 comments.xml 部件里。删批注要同时清掉这两边:正文锚点 + 批注部件里的 comment 节点。

最后 turn_off_track_changes() 把 settings.xml 里的 w:trackChanges 开关删掉,这样用户打开新文档后不会再自动进入修订模式。

运行结果

final_clean 目录里是清洗后的文档。打开后:所有批注气泡消失,所有修订痕迹变成普通文字(插入的内容保留、删除的内容消失),状态栏不再显示"修订: 打开"。可以安全发出去。

注意事项

  • 这是XML级别的粗暴处理,对绝大多数"正常修订"有效。如果文档里有复杂的移动修订、表格修订、批注嵌套,可能漏网,处理完务必抽查一份。
  • 本脚本是"接受所有修订",不是"拒绝所有修订"。如果要拒绝,逻辑反过来:保留 w:del 内容、删掉 w:ins 内容。
  • 删批注前确认所有批注意见都已经处理完,删了就找不回来了。
  • 处理完建议用Word打开看一眼"审阅-修订"面板,确认没有残留修订标记。
  • 加密文档、带宏的docm文件可能报错,会在控制台跳过。

Python Word批量去除批注与修订痕迹:清洗定稿

标签:

更新时间:2026-09-14 21:44:35

上一篇:Python Word设置首行缩进:批量调整段落格式

下一篇:Python Word批量删除空行方法