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

如何通过编程(如iText)处理PDF不规则对象,解决无法高亮文本问题?

问题描述
  • 文档存在不规则PDF对象,导致无法高亮选中目标文本
  • 需通过编程方式解决该问题,未找到有效线上方案
  • 已尝试用iText和Adobe执行flattening操作,但不确定是否能解决此问题
  • 相关参考截图:
    • 尝试高亮文本时的状态
    • PDF对象轮廓
    • 修复后的期望效果
核心原因分析

文本无法高亮选中,常见触发场景包括:

  • 文本被嵌入在矢量图形/图像对象中,未以可选中的字符流形式存在
  • 文本的字符编码、位置映射(CMAP)损坏,导致阅读器无法识别为可交互文本
  • PDF使用了非标准文本渲染模式(如将文本绘制为路径而非可选中字符)
关于Flattening操作的说明

Flattening仅用于将PDF中的动态元素(表单域、注释、图层)转换为静态页面内容,无法修复文本本身的可选中性问题。除非你的问题是浮动交互层遮挡了文本,否则该操作对当前场景无效。

编程解决方案

1. 文本提取重排重建

通过PDF处理库提取底层文本,重新生成结构规范的PDF,适合文本存在但结构异常的场景:

import fitz

def rebuild_pdf(input_path, output_path):
    doc = fitz.open(input_path)
    new_doc = fitz.open()
    for page in doc:
        new_page = new_doc.new_page(width=page.rect.width, height=page.rect.height)
        # 提取文本块并按原位置重绘
        blocks = page.get_text("blocks")
        for block in blocks:
            rect = fitz.Rect(block[:4])
            text = block[4]
            # 可根据需求指定匹配原文档的字体
            new_page.insert_text(rect.tl, text, fontsize=10)
        # 保留原页面背景(含图像、矢量图形)
        pix = page.get_pixmap()
        new_page.insert_image(page.rect, pixmap=pix, overlay=False)
    new_doc.save(output_path)
    new_doc.close()
    doc.close()

2. 修复文本坐标映射

针对文本存在但位置映射错误的情况,可使用PDFBox修复文本结构:

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.text.PDFTextStripper;
import org.apache.pdfbox.text.TextPosition;
import java.io.File;
import java.io.IOException;
import java.util.List;

public class FixTextSelectability {
    public static void main(String[] args) throws IOException {
        PDDocument doc = PDDocument.load(new File("input.pdf"));
        PDDocument newDoc = new PDDocument();
        
        for (PDPage page : doc.getPages()) {
            PDPage newPage = new PDPage(page.getMediaBox());
            newDoc.addPage(newPage);
            PDPageContentStream contentStream = new PDPageContentStream(newDoc, newPage);
            
            // 提取文本位置信息并重新写入
            PDFTextStripper stripper = new PDFTextStripper() {
                @Override
                protected void writeString(String text, List<TextPosition> textPositions) throws IOException {
                    for (TextPosition pos : textPositions) {
                        contentStream.beginText();
                        contentStream.setFont(pos.getFont(), pos.getFontSize());
                        contentStream.newLineAtOffset(pos.getX(), pos.getY());
                        contentStream.showText(pos.getUnicode());
                        contentStream.endText();
                    }
                }
            };
            stripper.processPage(page);
            contentStream.close();
        }
        newDoc.save("output.pdf");
        newDoc.close();
        doc.close();
    }
}

3. OCR识别重建(极端场景)

若文本完全以图像形式存在(如扫描件伪装成文本对象),需结合OCR工具识别后重新嵌入:

import fitz
import pytesseract
from PIL import Image

def ocr_rebuild_pdf(input_path, output_path):
    doc = fitz.open(input_path)
    new_doc = fitz.open()
    for page in doc:
        pix = page.get_pixmap()
        img = Image.frombytes("RGB", [pix.width, pix.height], pix.samples)
        # OCR识别文本内容
        ocr_text = pytesseract.image_to_string(img)
        new_page = new_doc.new_page(width=page.rect.width, height=page.rect.height)
        # 插入原图像作为背景
        new_page.insert_image(page.rect, pixmap=pix, overlay=False)
        # 插入透明文本(可选中且不遮挡背景)
        new_page.insert_text(fitz.Point(10, 20), ocr_text, fontsize=10, fill=(0,0,0,0))
    new_doc.save(output_path)
    new_doc.close()
    doc.close()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 22:23:17