用 Python 给 Word 文档加水印:文字、图片与批量处理

水印是覆盖在页面上的标记:它在每一页重复出现,位于正文下方,不占用段落空间,也不改变分页。Word 把水印保存在页眉层里,因此设置一次就能覆盖整份文档。

本文使用 Free Spire.Doc for Python :Document.Watermark 属性接收一个水印对象,文字与图片分别对应 TextWatermark 和 PictureWatermark。

bash 复制代码
pip install Spire.Doc.Free

水印在文档里的位置

页眉层是 Word 存放水印的地方。水印作为图形锚定在页眉中,所以它天然具备三个性质:每页重复、绘制在正文下层、不参与正文排版。设置水印不会改动已有的页眉文字,也不会影响页脚的页码域。

Document.Watermark 是一个可写属性:赋一个 TextWatermark 或 PictureWatermark 就设置水印,赋 None 就移除。再次赋值会替换已有的水印------这一点在批量处理时很有用,同一份文档可以先盖文字水印,再换成图片水印,最终只保留最后一次设置的内容。

类型 类 主要参数
文字水印 TextWatermark Text、FontName、FontSize、Color、Layout、Semitransparent
图片水印 PictureWatermark SetPicture、Scaling、IsWashout

文字水印

示例文档是一份 4 页的《支付网关接入规范 v2.3》,包含封面、三节正文、三个表格,页眉为文档名,页脚为页码。

python 复制代码
from spire.doc import *
from spire.doc.common import *

doc = Document()
doc.LoadFromFile("接入规范_v2.3.docx")

wm = TextWatermark()
wm.Text = "内部资料 · 禁止外传"
wm.FontName = "Microsoft YaHei"
wm.FontSize = 42
wm.Color = Color.get_Gray()
wm.Layout = WatermarkLayout.Diagonal
wm.Semitransparent = True
doc.Watermark = wm

doc.SaveToFile("接入规范_v2.3_文字水印.docx", FileFormat.Docx2016)
doc.Close()

Text 是水印文字,长度决定字号的上限。42 pt 的 8 个汉字沿对角线铺开约 12 cm,仍在 A4 版心内;如果再长,字号要相应调小。短标记(例如「作废」)可以放大到 60 pt。

FontName 对中文是必要项:中文字形由字体本身提供,Microsoft YaHei、SimSun 这类系统字体能保证每个汉字完整显示。

Color 与 Semitransparent 一起控制可见度。只把颜色调浅,文字仍然是实心填充,压在正文上会遮挡阅读;Semitransparent = True 让填充整体半透明,正文从水印后面透出来。示例用灰色加半透明,在封面与正文页上都保持可读。

Layout 取 Diagonal 或 Horizontal。对角线布局从页面左下延伸到右上,覆盖面积大,适合「内部资料」这类整页标记;水平布局更克制,适合页眉附近的小标记。

图片水印

python 复制代码
wm = PictureWatermark()
wm.SetPicture("watermark_northwind.png")
wm.Scaling = 70
wm.IsWashout = True
doc.Watermark = wm

图片水印对源图有两个要求。第一是透明背景:使用带 alpha 透明通道的 PNG,水印区域内只呈现图形本身,正文从透明部分透出来。第二是尺寸与缩放:源图是 640 × 200 像素,100% 时宽约 16.9 cm,超过 A4 版心宽度(约 14.7 cm);Scaling = 70 后约 11.8 cm,正好落在版心内。

IsWashout = True 把图片处理成浅色冲蚀效果,深色 Logo 变成淡蓝灰,压在文字上不挡字。设为 False 时保留原始颜色,适合作为空白区域或页面角落的实色标识。

图片水印的文件增长比文字水印明显:22,362 字节,比文字水印多 9,156 字节,因为 PNG 被嵌入文档。源图本身的复杂度直接决定增量,纯文字 Logo 通常只有几 KB。

批量处理

批量水印的循环结构和普通批处理一致:遍历目录、加载、设置水印、另存。每个文档重新构造一个水印对象,避免把同一个对象复用到多份文档上。

python 复制代码
import os, time

IN_DIR = "./历史版本"    # 接入规范_v2.0.docx 至 接入规范_v2.3.docx
OUT_DIR = "./加水印"

started = time.perf_counter()
for name in sorted(os.listdir(IN_DIR)):
    if not name.lower().endswith(".docx"):
        continue
    doc = Document()
    doc.LoadFromFile(os.path.join(IN_DIR, name))

    wm = TextWatermark()
    wm.Text = "内部资料 · 禁止外传"
    wm.FontName = "Microsoft YaHei"
    wm.FontSize = 42
    wm.Color = Color.get_Gray()
    wm.Layout = WatermarkLayout.Diagonal
    wm.Semitransparent = True
    doc.Watermark = wm

    doc.SaveToFile(os.path.join(OUT_DIR, name.replace(".docx", "_水印.docx")), FileFormat.Docx2016)
    doc.Close()
print("%.2f s" % (time.perf_counter() - started))

4 份历史版本(v2.0 至 v2.3)整批处理用时 0.55 秒,每份输出 13,206 字节。循环里对已带水印的文件同样适用:新的赋值会替换旧水印,不会叠加出两层标记。

移除水印

python 复制代码
doc = Document()
doc.LoadFromFile("接入规范_v2.3_文字水印.docx")
doc.Watermark = None
doc.SaveToFile("接入规范_无水印.docx", FileFormat.Docx2016)
doc.Close()

移除后仍是 4 页,文件 11,254 字节。页眉、页脚、表格与正文都保持原样,页面渲染后看不到任何水印残留。移除操作作用在另存的新文件上,原始的水印文档不受影响;需要保留历史版本时,输出文件名要与源文件区分开。

结果对比

把四份文件放在一起对比,页数与体积的变化可以直接说明水印的类型:

文件 页数 字节
接入规范_v2.3.docx 4 10,159
接入规范_v2.3_文字水印.docx 4 13,206
接入规范_v2.3_图片水印.docx 4 22,362
接入规范_无水印.docx 4 11,254

页数不变,说明水印没有挤动正文。渲染结果里,每一页都带有水印,正文在水印之上保持可读,页眉与页脚也没有被覆盖:文字水印在封面与三页正文上位置一致,图片水印在封面与正文页都落在版心中央,透明区域与页面内容自然融合。

文字水印、图片水印与移除水印之后的文件里,doc.Sections[0].HeadersFooters.Header 的段落文本都仍是「支付网关接入规范 v2.3」------水印与页眉文字是页眉层里相互独立的两层内容。

适用场景

水印适合标注文档的流转状态:内部资料、草稿、作废、评审稿、样张。文字水印用于状态说明,图片水印用于品牌或部门标识;两者也可以按批次切换------对外版本用文字,内部归档用 Logo。

水印承担视觉提示的职责;复制、编辑与打印的限制由文档保护或加密完成。水印让阅读者一眼看出文档的归属与状态。批量处理时,把水印设置与导出 PDF 串在同一条流水线上,可以在分发前同时完成标记与格式固定。

相关推荐
j7~1 小时前
【C++ 面试笔记】(篇二):类与数据抽象 & STL 容器与算法
开发语言·c++·面试·stl容器和算法·类和数据抽象
Android小码家1 小时前
framework&framework-minus-apex&android.jar的区别
android·python·jar
lee_curry1 小时前
第十周完整学习笔记:继续升级为“检索更准、权限安全、索引可维护、失败可恢复、长期可运行”的企业级 RAG 系统
python·ai·langchain·agent·langgraph
Fuyo_11191 小时前
深入解析 C++ unordered_set 与 unordered_map 的核心特性与性能实战
开发语言·c++
ShineWinsu2 小时前
对于Qt:QPushButton常见属性的解析
开发语言·c++·qt·api·gui·按钮·qpushbutton
外贸GEO优化2 小时前
外贸独立站的可抓取性:JS 渲染、懒加载与无限滚动到底影响什么
开发语言·javascript·ecmascript
飞浪纪元[FWC–FE]2 小时前
Qt 工程创建与 CMake / qmake 构建规范
开发语言·数据库·qt
Ivanqhz2 小时前
MoE + LLM 应用
数据库·人工智能·pytorch·python·深度学习·算法·1024程序员节