Python Word批量删除指定段落:按关键词清理
用python-docx批量删除Word文档中包含指定关键词、匹配正则或为空的段落,清理模板里的占位符、备注、空行,适合批量清洗合同、报告。
场景痛点
从旧模板复制出来的合同里,总残留"【此处填写XXX】""(备注:略)"这种占位符,要一份份手动找出来删。空段落一堆,排版难看。用Python扫描所有段落,按关键词或正则批量删,另存干净版本,比手工快十倍。
用到的库
pip install python-docx
完整代码
# -*- coding: utf-8 -*-
"""
批量删除 Word 文档中:
1) 包含指定关键词的段落
2) 完全为空的段落
3) 匹配正则的段落
"""
import re
from pathlib import Path
from docx import Document
def delete_paragraph(paragraph):
"""真正从 XML 里删掉一个段落(python-docx 没有直接删除API)"""
p = paragraph._element
p.getparent().remove(p)
# 释放引用
paragraph._p = paragraph._element = None
def clean_docx(docx_path: Path, output_path: Path,
keywords=None,
patterns=None,
remove_empty=True):
"""
keywords: 段落包含任一关键词就删
patterns: 段落匹配任一正则就删
remove_empty: 是否删除空段落
"""
keywords = keywords or []
patterns = patterns or []
compiled = [re.compile(p) for p in patterns]
doc = Document(str(docx_path))
deleted_kw = 0
deleted_re = 0
deleted_empty = 0
# 从后往前删,避免索引错乱
paragraphs = list(doc.paragraphs)
for para in reversed(paragraphs):
text = para.text.strip()
# 空段落
if remove_empty and not text:
delete_paragraph(para)
deleted_empty += 1
continue
# 关键词命中
if any(kw in text for kw in keywords):
delete_paragraph(para)
deleted_kw += 1
continue
# 正则命中
if any(pat.search(text) for pat in compiled):
delete_paragraph(para)
deleted_re += 1
continue
# 表格单元格里的段落也清一遍
for table in doc.tables:
for row in table.rows:
for cell in row.cells:
for para in reversed(list(cell.paragraphs)):
text = para.text.strip()
if remove_empty and not text:
delete_paragraph(para)
elif any(kw in text for kw in keywords):
delete_paragraph(para)
doc.save(str(output_path))
return {
"关键词删除": deleted_kw,
"正则删除": deleted_re,
"空段落删除": deleted_empty,
}
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
stats = clean_docx(
docx_file, out,
keywords=["【此处", "【填写", "(备注", "(注:"],
patterns=[r"^第?\s*[一二三四五六七八九十\d]+\s*页\s*$", # 页码行
r"^\s*第\s*[一二三四五六七八九十\d]+\s*节\s*$"],
remove_empty=True,
)
print(f"✓ {docx_file.name}: 关键词删{stats['关键词删除']} 正则删{stats['正则删除']} 空段删{stats['空段落删除']}")
if __name__ == "__main__":
batch_clean(
input_dir="./word_docs",
output_dir="./cleaned_docs",
)
代码讲解
python-docx 没有 paragraph.delete() 方法,因为段落是底层XML元素。delete_paragraph() 拿到段落的 _element,从它的父节点里 remove 掉,段落就真正从文档里消失了。
关键技巧:从后往前遍历(reversed(paragraphs))。如果从前往后删,删掉一个段落后后面的索引会前移,导致漏删。从后往前删不影响前面段落的索引。
三层过滤顺序:先判空,再判关键词,最后判正则。表格单元格里的段落也单独遍历一遍,因为 doc.paragraphs 不包含表格内段落。
正则示例里 ^\s*第?\s*[一二三四五六七八九十\d]+\s*页\s*$ 匹配"第3页""第十页"这种页眉页脚串到正文里的页码行,按自己文档情况改。
运行结果
cleaned_docs 目录里是清理后的文档。打开对照,所有"【此处…"占位符、备注行、空段落都没了。控制台打印每个文件删了多少段,数字为0说明该文档干净。
注意事项
- 删除是不可逆的,脚本只写到
output_dir,原文件不动,验证没问题再替换。 - 关键词匹配是"包含",想精确匹配改成
text == kw。注意中英文括号要对齐,模板里经常混用全角半角。 - 表格里的段落删除逻辑写得简化了,正则那部分没重复,可以按需补全。
- 段落样式(标题、列表)会跟着段落一起被删掉,别误删了标题层级。
- 如果文档用了分节符,分节符存在最后一段的段落标记里,删到最后一段可能影响分节,脚本默认保留非空段落所以安全。

更新时间:2026-09-15 08:53:55