我的知识记录

Python给PDF添加文字水印:PyMuPDF批量防泄密

用Python的PyMuPDF(fitz)给PDF每一页打上斜半透明文字水印,支持自定义文字、字号、颜色、角度和透明度,一行命令批量处理整个文件夹。

场景痛点

发出去的报价单、合同、方案,总担心被转发后追溯不到源头。手动在Adobe里设置水印一页页拖,几十页上百个文件根本扛不住。用Python的PyMuPDF直接遍历每一页,把"内部资料 禁止外传"这类文字以斜45度、灰色半透明铺在页面中央,几秒就能处理完整个文件夹。

用到的库

pip install pymupdf

完整代码

# -*- coding: utf-8 -*-
"""
用 PyMuPDF(fitz) 给 PDF 每一页添加斜向半透明文字水印。
"""
import fitz  # PyMuPDF
from pathlib import Path


def add_text_watermark(input_pdf: str,
output_pdf: str,
watermark_text: str = "内部资料 禁止外传",
font_size: int = 36):
doc = fitz.open(input_pdf)

for page in doc:
# 取页面中心点,水印从这里开始绘制
rect = page.rect
cx, cy = rect.width / 2, rect.height / 2

# insert_text 不支持旋转,用 insert_textbox 配合 morph 矩阵实现斜45度
# 颜色用灰色 (0.5, 0.5, 0.5),通过 fill_opacity 控制透明度
# 用 morph 参数做旋转:point=(cx,cy), matrix 旋转 45 度
mat = fitz.Matrix(1, 1).prerotate(45)

# 先估算文字宽度,让它真正居中
# 用 insert_textbox 画一个足够大的矩形,文字水平居中
text_width = fitz.get_text_length(watermark_text, fontname="china-s", fontsize=font_size)
box = fitz.Rect(cx - text_width / 2 - 50,
cy - font_size,
cx + text_width / 2 + 50,
cy + font_size)

page.insert_textbox(
box,
watermark_text,
fontsize=font_size,
fontname="china-s",     # PyMuPDF 内置简体中文字体
color=(0.7, 0.7, 0.7),
fill_opacity=0.35,     # 透明度 0~1,0 全透明
morph=(fitz.Point(cx, cy), mat),
align=1,                # 1=居中
)

doc.save(output_pdf, garbage=3, deflate=True)
doc.close()
print(f"水印完成:{output_pdf}")


def batch_watermark(input_dir: str, output_dir: str, watermark_text: str):
src = Path(input_dir)
dst = Path(output_dir)
dst.mkdir(parents=True, exist_ok=True)

for pdf_file in src.glob("*.pdf"):
out = dst / pdf_file.name
add_text_watermark(str(pdf_file), str(out), watermark_text)


if __name__ == "__main__":
batch_watermark(
input_dir="originals",
output_dir="watermarked",
watermark_text="内部资料 严禁外传",
)

代码讲解

  • fitz.open() 打开PDF,doc是一个文档对象,for page in doc 遍历每一页。
  • fontname="china-s" 是PyMuPDF内置的简体中文字体,不需要额外装字体文件,写中文直接可用,这是它比reportlab省事的地方。
  • fill_opacity=0.35 控制填充透明度,0.3~0.5 之间比较常见,既能看见又不挡正文。
  • morph=(point, matrix) 是PyMuPDF做旋转、缩放的通用手段,这里配合prerotate(45)把文字旋转45度斜铺。
  • insert_textboxinsert_text 多了自动换行和对齐,align=1 水平居中。
  • 保存时加 garbage=3, deflate=True 顺手清掉冗余对象并压缩,不会让水印后的文件变大很多。

运行结果

把原始PDF放进originals/文件夹,脚本跑完会在watermarked/里生成同名文件,每页中央都有斜45度的灰色半透明"内部资料 严禁外传"字样,正文依然清晰可读。

注意事项

  • PyMuPDF 从 1.22 左右开始包名改成 pymupdf,旧教程里 import fitz 依然可用;pip 安装用 pip install pymupdf
  • insert_textbox 在文字过长超出矩形时会返回剩余高度(负数),如果水印被截断,把box范围放大或调小font_size
  • 扫描件PDF(图片型)加水印一样有效,水印会盖在图片上面。
  • 想要铺满整页而不是只放一行,就循环多次调用 insert_textbox,y坐标按行距平铺。

Python给PDF添加文字水印:PyMuPDF批量防泄密

标签:

更新时间:2026-09-14 21:41:18

上一篇:Python批量为PDF添加公司Logo页眉:每页统一抬头

下一篇:Python批量给PDF添加页码 底部居中教程