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

如何用Python结合AWS Textract为PDF添加可搜索OCR隐形文本?

用AWS Textract生成可搜索PDF的Python实现方案

核心思路

利用AWS Textract的OCR结果(包含文本内容和坐标信息),通过PyMuPDF将文本以隐形模式插入PDF对应位置,实现可搜索功能。隐形文本不会显示在页面上,但能被PDF阅读器识别并支持搜索,无需严格匹配原字体样式。

关键步骤与代码实现

1. 获取AWS Textract OCR结果

调用Textract的analyze_document接口,按页面整理LINE/WORD类型的识别结果,包含文本内容和几何坐标。

import boto3
import fitz  # PyMuPDF

def fetch_textract_ocr(pdf_file_path):
    textract_client = boto3.client('textract')
    with open(pdf_file_path, 'rb') as pdf_file:
        response = textract_client.analyze_document(
            Document={'Bytes': pdf_file.read()},
            FeatureTypes=['TEXT']  # 仅提取文本相关信息
        )
    
    # 按页面索引(0开始)整理结果
    page_ocr_data = {}
    for block in response['Blocks']:
        if block['BlockType'] == 'PAGE':
            page_idx = block['Page'] - 1  # 转换为PyMuPDF的0索引
            page_ocr_data[page_idx] = []
        elif block['BlockType'] in ['LINE', 'WORD']:
            page_idx = block['Page'] - 1
            if page_idx in page_ocr_data:
                page_ocr_data[page_idx].append(block)
    return page_ocr_data

2. 坐标转换与隐形文本插入

Textract采用左上角原点的相对坐标(0-1),而PyMuPDF采用左下角原点的绝对坐标,需先完成坐标转换,再插入隐形文本。

def inject_invisible_searchable_text(input_pdf, output_pdf, ocr_results):
    pdf_doc = fitz.open(input_pdf)
    
    for page_idx in range(len(pdf_doc)):
        page = pdf_doc[page_idx]
        page_rect = page.rect
        page_width = page_rect.width
        page_height = page_rect.height
        
        current_page_blocks = ocr_results.get(page_idx, [])
        if not current_page_blocks:
            continue
        
        # 判断页面是否已有可搜索文本,纯图片页才需要添加(可根据需求调整)
        has_existing_text = bool(page.get_text().strip())
        if not has_existing_text:
            for block in current_page_blocks:
                # 跳过无几何信息的块
                if 'Geometry' not in block:
                    continue
                
                # 优先使用Polygon计算精确文本区域,替代BoundingBox
                polygon = block['Geometry']['Polygon']
                # 转换Polygon坐标到PyMuPDF坐标系
                converted_points = [
                    (p['X'] * page_width, page_height - p['Y'] * page_height)
                    for p in polygon
                ]
                # 生成文本对应的Rect区域
                x_coords = [p[0] for p in converted_points]
                y_coords = [p[1] for p in converted_points]
                text_rect = fitz.Rect(
                    min(x_coords), min(y_coords),
                    max(x_coords), max(y_coords)
                )
                
                # 插入隐形文本:使用TEXT_INVISIBLE标志,无需匹配原字体
                text_content = block['Text']
                # 字体大小设为文本区域高度的90%,确保文本完全容纳
                font_size = text_rect.height * 0.9
                
                page.insertTextbox(
                    text_rect,
                    text_content,
                    fontsize=font_size,
                    fontname="helv",  # 通用无衬线字体
                    text_flags=fitz.TEXT_INVISIBLE,
                    align=fitz.TEXT_ALIGN_LEFT
                )
    
    pdf_doc.save(output_pdf)
    pdf_doc.close()

3. 主流程调用

if __name__ == "__main__":
    input_path = "source.pdf"
    output_path = "searchable_output.pdf"
    ocr_data = fetch_textract_ocr(input_path)
    inject_invisible_searchable_text(input_path, output_path, ocr_data)

针对你的问题的优化建议

  1. 字体与对齐问题:由于插入的是隐形文本,无需匹配原字体样式。通过文本区域高度自动计算字体大小,左对齐即可满足搜索需求,用户完全看不到文本,样式不影响使用。
  2. 多类型PDF适配:
    • 纯图片PDF:直接插入隐形文本即可。
    • 纯可搜索PDF:可通过page.get_text()判断,选择跳过或补充缺失文本(如扫描件嵌入的文本不全时)。
    • 混合PDF:结合page.get_image_info()判断页面是否包含图片,针对性补充隐形文本。
  3. 精度提升:优先使用Textract返回的Polygon坐标生成文本区域,比BoundingBox更贴合实际文本位置,避免空白区域的无效文本插入。

注意事项

  • 确保AWS账号拥有Textract的调用权限,并配置好本地AWS凭证。
  • 对于大文件,可考虑分页处理,避免内存占用过高。
  • 若需要处理多语言文本,可在Textract调用时指定LanguageCode参数,提高识别准确率。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 21:07:30