You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何替换PDF隐藏文本层文本,使复制粘贴时替换内容位置正确

你遇到的问题是fitz的红框注释默认将替换文本作为独立内容流追加到页面末尾,没有融入原文本的排版顺序结构,因此跨区域复制文本或者全页提取时,替换内容不会出现在原有位置。


可行实现方案

方案1:重写整页文本(兼容性最好,文本顺序100%匹配原排版)

该方案通过先提取全页结构化文本,替换敏感词后重新写入页面,同时绘制遮盖矩形保证图像层敏感内容被覆盖,完全符合复制粘贴的顺序要求。

import fitz

phrase_to_redact = "example"
placeholder = "x" * len(phrase_to_redact)  # 等长占位符
color = (1, 1, 1)  # 白色填充,可按需调整
path = "你的文件路径.pdf"

doc = fitz.open(path)
for page in doc:
    # 第一步:提取页面所有带格式的文本块
    blocks = page.get_text("dict", flags=fitz.TEXTFLAGS_TEXT)["blocks"]
    new_blocks = []
    redact_rects = []
    
    for block in blocks:
        if block["type"] != 0:  # 非文本块直接保留(图片、矢量图等)
            new_blocks.append(block)
            continue
        for line in block["lines"]:
            for span in line["spans"]:
                # 查找包含敏感词的文本片段
                if phrase_to_redact in span["text"]:
                    # 记录要遮盖的坐标
                    redact_rects.append(fitz.Rect(span["bbox"]))
                    # 替换敏感词为占位符
                    span["text"] = span["text"].replace(phrase_to_redact, placeholder)
        new_blocks.append(block)
    
    # 第二步:清空原页面所有内容
    page.clean_contents()
    page.clear()
    
    # 第三步:把修改后的文本块按原顺序写回页面
    for block in new_blocks:
        if block["type"] != 0:
            # 非文本块原样插入
            page.insert_image(block["bbox"], stream=block["image"])
            continue
        for line in block["lines"]:
            for span in line["spans"]:
                # 按原字体、字号、坐标插入修改后的文本
                page.insert_text(
                    (span["bbox"][0], span["bbox"][3] - span["descender"]),  # 文本基线坐标
                    span["text"],
                    fontsize=span["size"],
                    fontname=span["font"],
                    color=fitz.sRGB_to_pdf(span["color"])
                )
    
    # 第四步:绘制填充矩形遮盖图像层可能残留的敏感内容
    for rect in redact_rects:
        page.draw_rect(rect, color=color, fill=color, overlay=True)

doc.save("替换后文件.pdf", garbage=4, deflate=True)

方案2:基于红框注释的轻量修改(适合小范围替换场景)

如果不想重写全页内容,可以在应用红框注释后,手动调整内容流的顺序,将替换文本插入到原内容的对应位置,PyMuPDF 1.20+版本支持page.move_contents()方法调整内容流顺序:

import fitz

phrase_to_redact = "example"
placeholder = "x" * len(phrase_to_redact)
color = (1,1,1)
path = "你的文件路径.pdf"

doc = fitz.open(path)
for page in doc:
    rects = page.search_for(phrase_to_redact)
    # 记录原内容流长度
    orig_contents_len = len(page.get_contents())
    for rect in rects:
        page.add_redact_annot(rect, text=placeholder, fill=color)
    page.apply_redactions()
    # 把新增的替换文本内容流移到对应位置,匹配原排版顺序
    new_contents = page.get_contents()[orig_contents_len:]
    for xref in new_contents:
        page.move_contents(xref, 0)

doc.save("替换后文件.pdf", garbage=4, deflate=True)

注意事项

  • 方案1的兼容性更好,几乎适配所有PDF阅读器的文本复制逻辑,同时能保证图像层和文本层的敏感内容都被彻底覆盖
  • 等长占位符建议使用同宽度字符(比如全角x或者*),避免替换后文本排版错位
  • 处理带特殊字体的PDF时,如果出现插入文本字体不匹配的问题,可以提前把字体嵌入到PDF文件中

内容的提问来源于stack exchange,提问作者nietoperz21

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 12:27:02