news 2026/4/16 0:24:46

PDFLoader 中的 OCR 文字提取实现详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
PDFLoader 中的 OCR 文字提取实现详解

1. 背景与动机

默认的langchain_community.document_loaders.PyPDFLoader虽然支持extract_images参数,但在某些场景下,它并不会自动将 OCR 识别后的文字合并到page_content中。为了确保能够百分之百提取出 PDF 页面中嵌入的图像文字(如电路图标签、截图文字等),我们采用了Mix-in (混合)模式:在保留原生文本层提取能力的同时,手动插入自定义的 OCR 处理流程。


2. 核心技术栈

  • pypdf: 用于底层的 PDF 页面解析和原始图片对象提取。
  • rapidocr-onnxruntime: 核心 OCR 引擎。
    • 优势:基于 ONNX Runtime,运行速度快,且不需要安装 Tesseract 等系统级组件,完全通过 Python 包分发。
  • Pillow (PIL): 用于处理从 PDF 中提取出的二进制图片数据。

3. 逻辑流程图 (Mermaid)

开始 load_file

初始化 PyPDFLoader

调用 loader.load 提取文本层

extract_images == True?

合并文本 & 返回 Document

进入 _enrich_with_ocr

初始化 RapidOCR 引擎

PdfReader 读取原始文件

遍历请求的页面

页面是否有图片?

提取图片数据 Bytes

RapidOCR 执行识别

将识别文字追加到 Page Content

跳过

所有页面处理完成?

结束


4. 代码深度讲解

4.1load_file方法:逻辑枢纽

load_file是外部调用的主入口,它负责协调文本提取和 OCR 增强。

defload_file(self,source:str,**kwargs)->Document:# ... 略过参数获取和日志打印# 1. 初始化 LangChain 的 PyPDFLoaderloader=PyPDFLoader(file_path=source,extract_images=extract_images,# 告诉底层库我们要处理图像password=password)# 2. 提取文本层 (Native Text Layer)# 这一步会利用 pypdf 提取 PDF 中原本就是文本的内容,返回一个 List[Document]documents=loader.load()# 3. 页面过滤# 如果用户指定了特定页面(如 pages=[10]),我们在这里进行筛选ifpages:filtered_docs=[]forpage_numinpages:idx=page_num-1if0<=idx<len(documents):filtered_docs.append(documents[idx])documents=filtered_docs# 4. 【关键步骤】OCR 文本增强# 如果 extract_images 为 True,则进入我们自定义的 OCR 流程ifextract_images:self._enrich_with_ocr(documents,source,pages)# 5. 内容合并# 将处理后的各页内容用 "--- Page Break ---" 标记拼接成一个完整的字符串combined_content="\n\n--- Page Break ---\n\n".join(doc.page_contentfordocindocuments)# 6. 返回结果# 返回一个包含完整文本和元数据的 Document 对象returnDocument(page_content=combined_content,metadata=metadata)

4.2_enrich_with_ocr方法:技术核心

该方法负责底层的图像提取和 OCR 识别。

A. 引擎延迟加载
try:fromrapidocr_onnxruntimeimportRapidOCR ocr_engine=RapidOCR()exceptImportError:# 如果没装包,优雅降级,打印警告logger.warning("rapidocr-onnxruntime not installed. Skipping OCR for images.")return

讲解:我们没有在文件顶部全局导入 RapidOCR,而是放在方法内部。这样如果用户不需要 OCR 功能,就不必承担加载庞大 OCR 模型的时间和内存开销。

B. 页面索引映射
reader=pypdf.PdfReader(source)# 使用原生 pypdf 读取# 如果指定了 [1, 3] 页,doc_page_indices 会变成 [0, 2]ifrequested_pages:doc_page_indices=[p-1forpinrequested_pages]else:doc_page_indices=list(range(len(documents)))

讲解:这是一个坑点。documents列表的长度取决于你加载了多少页。如果只加载了第 10 页,documents长度就是 1,索引是 0。但我们需要告诉pypdf去读取原文件的第 9 个索引。这段逻辑保证了“索引对位”。

C. 图片提取与 OCR
fori,page_idxinenumerate(doc_page_indices):page=reader.pages[page_idx]images=page.images# 获取页面所有图片对象ocr_texts=[]forimageinimages:# image.data 直接拿到图片的 Bytes 数据result,_=ocr_engine(image.data)ifresult:# RapidOCR 返回结果格式:[[[box], text, score], ...]# 我们通过列表推导式 line[1] 拿到纯文字部分text="\n".join([line[1]forlineinresult])iftext.strip():# 包装识别出的文字,打上标签ocr_texts.append(f"[Image Text]:\n{text}")

讲解:

  • 我们利用了pypdf6.x 版本的新特性,可以直接通过page.images访问图片。
  • image.data是内存中的字节流,避免了 IO 读写临时文件的损耗。
  • ocr_engine(image.data)是最核心的识别动作。
D. 就地修改(In-place Update)
ifocr_texts:# 将识别到的文字追加到对应 Document 对象的原有文本后面documents[i].page_content+="\n\n"+"\n\n".join(ocr_texts)

讲解:这种设计模式不会创建新的 Document 对象,而是直接修改传入的列表对象,节省了内存空间。


5. 完整代码参考

以下是src/loaders/pdf_loader.py中关键方法的完整实现:

5.1load_file方法

defload_file(self,source:str,**kwargs)->Document:try:extract_images=kwargs.get('extract_images',False)pages=kwargs.get('pages',None)password=kwargs.get('password',None)logger.info(f"Loading PDF:{source}")loader=PyPDFLoader(file_path=source,extract_images=extract_images,password=password)documents=loader.load()ifnotdocuments:raiseValidationError(message="PDF is empty",error_code="EMPTY_PDF",source=source)ifpages:filtered_docs=[]forpage_numinpages:idx=page_num-1if0<=idx<len(documents):filtered_docs.append(documents[idx])documents=filtered_docsifextract_images:self._enrich_with_ocr(documents,source,pages)combined_content="\n\n--- Page Break ---\n\n".join(doc.page_contentfordocindocuments)metadata=documents[0].metadata.copy()ifdocumentselse{}metadata.update({'source':source,'file_type':'pdf','total_pages':len(documents),'file_size':Path(source).stat().st_size})returnDocument(page_content=combined_content,metadata=metadata)exceptExceptionase:raiseValidationError(message=str(e),error_code="PDF_LOAD_ERROR",source=source)frome

6. 测试验证

为了验证 OCR 功能,我们编写了专门的测试用例来检查第 10 页(包含产品框图)的内容提取情况。

6.1 测试代码 (test/loaders/test_pdf_loader.py)

deftest_load_file_with_images(self,loader):"""Test loading file with image extraction enabled."""PAGE_NUM=10document=loader.load_file(PDF_PATH,extract_images=True,pages=[PAGE_NUM])assertlen(document.page_content)>0print(f"\n=== Page{PAGE_NUM}Content (Image Extraction Enabled) ===")print(document.page_content)

6.2 测试输出结果

2025-12-28 01:29:06.981 | DEBUG | src.loaders.pdf_loader:_enrich_with_ocr:162 - Added OCR text from 6 images to page 10 === Page 10 Content (Image Extraction Enabled) === | 1 - 产品介绍 图 1-1 昉·星光 2 产品框图(顶部视图) ... (原生文本) ... [Image Text]: StarFive VisionFive 2 AE 888 ...

7. 实现的优势

  1. 零系统依赖:完全通过 Python 包实现 OCR。
  2. 强制增强:弥补了PyPDFLoader默认对图片文字提取不力的问题。
  3. 精准映射:支持特定页面的 OCR 提取。

8. 依赖说明 (requirements.txt)

pypdf==6.5.0 Pillow==12.0.0 rapidocr-onnxruntime==1.4.4
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/15 16:13:01

自动化3D建模效率提升方案:腾讯混元3D-Part商业技术分析报告

自动化3D建模效率提升方案&#xff1a;腾讯混元3D-Part商业技术分析报告 【免费下载链接】Hunyuan3D-Part 腾讯混元3D-Part 项目地址: https://ai.gitcode.com/tencent_hunyuan/Hunyuan3D-Part 执行摘要 在当前的3D内容生产生态中&#xff0c;传统建模工作流面临着显著…

作者头像 李华
网站建设 2026/4/16 12:24:00

终极OpenWrt路由器改造方案:从基础刷机到高级配置完全指南

还在为路由器功能单一、性能瓶颈而烦恼吗&#xff1f;OpenWrt作为开源路由器操作系统的领先者&#xff0c;能够彻底改变你的网络体验。本文将带你从零开始&#xff0c;掌握OpenWrt刷机的完整流程&#xff0c;让你的路由器脱胎换骨&#xff0c;拥有无限扩展可能&#xff01; 【免…

作者头像 李华
网站建设 2026/4/16 10:45:12

重庆DEM数据终极指南:如何快速获取高精度高程数据

重庆DEM数据终极指南&#xff1a;如何快速获取高精度高程数据 【免费下载链接】重庆地区DEM数据集 探索重庆的地理奥秘&#xff0c;这份DEM数据集为你提供了详尽的高程、等高线与路网信息。无论是专业GIS分析还是三维可视化&#xff0c;tif、kmz和kml格式的多样选择都能满足你的…

作者头像 李华
网站建设 2026/4/16 11:08:36

Dockge终极指南:轻松实现Docker Compose一键管理

Dockge终极指南&#xff1a;轻松实现Docker Compose一键管理 【免费下载链接】dockge A fancy, easy-to-use and reactive self-hosted docker compose.yaml stack-oriented manager 项目地址: https://gitcode.com/GitHub_Trending/do/dockge Dockge是一款现代化的Dock…

作者头像 李华
网站建设 2026/4/16 12:47:15

3步快速掌握InstantID与Blender融合:零训练3D人脸建模终极教程

3步快速掌握InstantID与Blender融合&#xff1a;零训练3D人脸建模终极教程 【免费下载链接】InstantID 项目地址: https://gitcode.com/gh_mirrors/in/InstantID 还在为3D人脸建模的复杂流程而头疼吗&#xff1f;今天我要分享一个革命性的解决方案&#xff1a;将Instan…

作者头像 李华
网站建设 2026/4/16 11:03:28

计算机毕业设计|基于springboot + vue外卖点餐系统(源码+数据库+文档)

外卖点餐 目录 基于springboot vue外卖点餐系统 一、前言 二、系统功能演示 详细视频演示 三、技术选型 四、其他项目参考 五、代码参考 六、测试参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 基于springboot vue外卖点餐系统 一、前言 博主介绍&am…

作者头像 李华