基于 Docling + PaddleOCR 的 PDF/图片文档智能解析系统

基于 Docling + PaddleOCR 的 PDF/图片文档智能解析系统 摘要在 RAG 知识库、企业资料归档、票据录入、合同审查和自动化办公项目中真正影响后续效果的往往不是大模型本身而是更前面的“文档能不能被稳定解析”。真实资料可能是 PDF、扫描件、图片票据、项目说明书、合同、论文或截图。如果这些文件无法先转换成结构化文本后面的检索、问答、摘要、字段抽取和审核流程都会受到影响。本文围绕一个完整的 AI 项目实战案例设计并实现一个基于 Docling PaddleOCR 的 PDF/图片文档智能解析系统。系统支持 PDF、图片、TXT、Markdown 等文件输入能够根据文件类型自动路由到不同解析后端并统一导出 Markdown 与 JSON。项目同时保留轻量 fallback即使没有安装 Docling 和 PaddleOCR也可以先运行内置 Demo生成解析结果、结构化文件和演示截图安装增强依赖后则可以进一步用于更接近真实业务的 PDF 版面解析与图片 OCR 识别。关键词DoclingPaddleOCRPDF 解析OCR 识别Markdown 导出JSON 结构化FastAPI文档智能处理RAG 数据预处理一、项目背景与效果预览很多 AI 应用文章会直接从“知识库问答”或“大模型总结”开始但真实工程里首先要解决的是资料入口问题。PDF 里可能有文本层也可能只是扫描图片票据图片可能倾斜、模糊或有反光说明书和报告里还有标题、段落、表格、编号和页码。如果直接把原始文件丢给后续系统常见问题主要有三类。第一文本抽取不完整。普通 PDF 可以用文本抽取工具读取一部分内容但扫描 PDF 或截图本质上是图片没有 OCR 就无法得到正文。第二结构丢失严重。很多脚本只会把文档变成一串连续文字标题层级、表格和段落关系被打散。第三后续应用难以复用。RAG、字段抽取、自动摘要和问答系统更适合接收 Markdown、JSON 或按块整理好的文本而不是混乱的原始文件。因此这个项目定位在大模型应用的前置环节把 PDF 和图片资料解析成可复用的结构化结果。Docling 负责增强 PDF/复杂文档解析PaddleOCR 负责图片 OCRPyMuPDF、pdfplumber 和 sidecar 文本则作为离线演示 fallback保证项目首次运行不被大依赖和模型下载卡住。项目运行后会生成两类结果一类是文档解析输出包括 Markdown、JSON 和运行日志另一类是博客展示图片包括系统架构图、解析流程图、Web 页面截图和批量解析结果截图。系统架构如下文档解析流程如下Web 首页支持上传文件、运行内置 Demo、查看接口状态和下载结果票据、合同扫描件和拍照文档是 OCR 系统最常见的输入。下面这张真实票据照片展示了拍摄角度、褶皱和光照不均等问题也解释了为什么项目需要保留 OCR 后端和结果结构化导出运行内置 Demo 后系统会把demo_data/中的 PDF、图片、TXT、Markdown 文件依次解析并把结果保存到outputs/markdown/和outputs/json/。运行结果示例如下命令行会输出类似结果Running Document AI Parser demo... Parsed 4 files. - sample_invoice.txt - builtin_text_reader - sample_project_manual.md - builtin_text_reader - sample_receipt.png - sidecar_ocr_demo - sample_report.pdf - pymupdf_fallback Runtime screenshots saved to images/results. Demo finished.其中pymupdf_fallback和sidecar_ocr_demo是离线演示模式下的兜底路径。如果安装了 Docling 和 PaddleOCRPDF 解析会优先走docling图片识别会优先走paddleocr。二、PaddleOCR 真实检测与识别效果为了让读者直观看到 OCR 后端的实际作用下面插入几张来自 PaddleOCR 官方文档的真实效果图。这些图片不是本项目手绘示意图而是 PaddleOCR 文档中用于展示通用 OCR、文本检测和文本识别模块的可视化结果。它们说明了 OCR 流程中“先定位文字区域再识别文字内容”的基本过程。通用 OCR Pipeline 示例可以看到模型先从图片中定位文字区域再输出对应文本图源PaddleOCR 官方 General OCR Pipeline Usage Tutorial页面地址https://www.paddleocr.ai/main/en/version3.x/pipeline_usage/OCR.html文本检测模块会在自然场景图片中标出文字框后续识别模块再针对这些区域做文本识别图源PaddleOCR 官方 Text Detection Module页面地址https://www.paddleocr.ai/main/en/version3.x/module_usage/text_detection.html文本识别模块则关注单行或局部文本图像输出识别文本和置信度图源PaddleOCR 官方 Text Recognition Module页面地址https://www.paddleocr.ai/main/en/version3.x/module_usage/text_recognition.html本文项目中的OCRParser封装的是这个思路真实环境下优先调用 PaddleOCR如果当前环境没有安装 OCR 依赖内置 Demo 会读取sample_receipt.png.gt.txt作为 sidecar 演示文本让导出、日志、Web 展示这些工程链路仍然完整跑通。三、系统设计与项目结构系统整体流程可以概括为上传文件或读取内置样例判断文件类型PDF/TXT/Markdown 进入文档解析链路图片进入 OCR 链路随后统一清洗文本、提取表格、补充元数据最后导出 Markdown 和 JSON并在 Web 页面中展示结果。上传文件 / 内置样例 ↓ 判断文件类型 ↓ PDF / TXT / MD → DoclingParser 图片文件 → OCRParser ↓ 文本清洗与统一结构 ↓ 表格提取与元数据补充 ↓ 导出 Markdown / JSON ↓ Web 页面展示 / 后续接入 RAG项目没有把所有逻辑写进一个脚本而是拆成几个职责清晰的模块。document_router.py负责根据后缀选择 PDF 解析或 OCR 解析docling_parser.py负责 Docling 优先、PyMuPDF/pdfplumber fallback 的文档解析ocr_parser.py负责 PaddleOCR 优先、sidecar demo fallback 的图片识别markdown_exporter.py负责导出 Markdown 和 JSONbatch_runner.py负责批量解析流程schema.py则提供统一的解析结果数据结构。完整目录结构如下document_ai_parser/ ├── blog.md ├── README.md ├── requirements.txt ├── requirements_ai.txt ├── app.py ├── run_demo.py ├── run.bat ├── run.sh ├── configs/ │ └── config.yaml ├── src/ │ ├── schema.py │ ├── utils.py │ ├── config_loader.py │ ├── table_extractor.py │ ├── docling_parser.py │ ├── ocr_parser.py │ ├── document_router.py │ ├── markdown_exporter.py │ ├── batch_runner.py │ └── screenshot_generator.py ├── templates/ │ └── index.html ├── static/ │ ├── style.css │ └── app.js ├── demo_data/ │ ├── sample_project_manual.md │ ├── sample_invoice.txt │ ├── sample_report.pdf │ ├── sample_receipt.png │ └── sample_receipt.png.gt.txt ├── outputs/ │ ├── markdown/ │ ├── json/ │ └── logs/ ├── weights/ │ └── README_WEIGHTS.md ├── images/ │ ├── figures/ │ └── results/ └── docs/ ├── api_design.md ├── common_errors.md └── deployment.md其中最重要的是src/、demo_data/和outputs/。demo_data/保证项目首次运行就有可解析文件outputs/保存运行结果images/保存文章配图和运行截图。四、运行配置与核心实现建议 Python 使用 3.10 或 3.11。先安装轻量依赖pipinstall-rrequirements.txt运行内置 Demopython run_demo.py启动 Web 系统python app.py浏览器访问浏览器访问运行日志中显示的本地地址如果需要启用 Docling 和 PaddleOCR 的增强能力可以额外安装pipinstall-rrequirements_ai.txt增强依赖单独放在requirements_ai.txt中是因为 Docling、PaddleOCR、PaddlePaddle 可能涉及较大的依赖、模型缓存和平台适配。项目教学和演示阶段先保证基础 Demo 能跑通实际部署时再按机器环境安装增强后端这样更适合源码交付和课程实践。统一结果结构。项目中所有解析器都会返回同一个ParseResult这样无论文档来自 PDF、图片还是 Markdown后续导出逻辑都不需要关心具体解析引擎。dataclassclassParseResult:source_path:strsource_name:strdoc_type:strengine:strtitle:strtext:strtables:List[ParsedTable]field(default_factorylist)metadata:Dict[str,Any]field(default_factorydict)warnings:List[str]field(default_factorylist)这里最关键的是text、tables、metadata和warnings。text保存正文内容tables保存提取到的表格metadata记录页数、解析说明等信息warnings用来告诉用户当前是否走了 fallback是否需要安装增强依赖。文档路由器。document_router.py根据文件后缀选择解析器。图片走 OCRPDF/TXT/MD 走文档解析。classDocumentRouter:defparse(self,path:str|Path)-ParseResult:pathPath(path)suffixpath.suffix.lower()ifsuffixin{.png,.jpg,.jpeg,.bmp,.tif,.tiff,.webp}:returnself.ocr_parser.parse(path)ifsuffixin{.pdf,.md,.txt}:returnself.docling_parser.parse(path)raiseValueError(fUnsupported file type:{suffix})这个模块虽然简单但工程价值很高。后续如果要扩展 DOCX、PPTX、HTML、Excel只需要在这里补充后缀并在对应解析器中实现解析逻辑即可。PDF 解析链路。docling_parser.py会先尝试导入 Doclingfromdocling.document_converterimportDocumentConverter converterDocumentConverter()convertedconverter.convert(str(path))docconverted.document markdowndoc.export_to_markdown()如果用户环境中没有安装 Docling则自动走 PyMuPDF fallbackimportfitzwithfitz.open(path)asdoc:foridx,pageinenumerate(doc,start1):page_textpage.get_text(text).strip()ifpage_text:pages.append(fPage{idx}\n\n{page_text})这种设计既保留了真实业务需要的 Docling 能力又保证教学环境中不会因为大依赖缺失直接失败。对于带文本层的 PDFPyMuPDF fallback 可以提取正文对于扫描件则建议安装 Docling/PaddleOCR 后再处理。图片 OCR 链路。ocr_parser.py先尝试加载 PaddleOCRfrompaddleocrimportPaddleOCR self._ocrPaddleOCR(use_angle_clsTrue,langself.lang)rawocr.ocr(str(path),clsTrue)考虑到 PaddleOCR 不同版本的返回结构可能存在差异项目写了_flatten_paddle_result方法递归提取识别文本。这样在版本升级时代码更容易兼容。如果没有安装 PaddleOCR内置 Demo 会读取sample_receipt.png.gt.txt。这个 sidecar 文件相当于演示环境下的 OCR 文本让项目在离线环境中也可以跑完整流程。导出与 Web 服务。markdown_exporter.py负责把ParseResult保存成 Markdown 和 JSON。Markdown 中包含解析信息、正文内容、表格结构和元数据导出目录分别是outputs/markdown/和outputs/json/。FastAPI 页面提供首页、健康检查、运行 Demo、上传解析和结果下载接口主要路径包括GET / Web 首页 GET /api/health 服务健康检查 POST /api/parse_demo 运行内置 Demo POST /api/upload 上传并解析单个文件 GET /api/download/... 下载 Markdown 或 JSON配置与示例数据。项目把运行目录、输出目录、解析偏好放在configs/config.yaml中而不是把路径写死在代码里。这样读者拿到源码后可以直接改配置。runtime:output_markdown_dir:outputs/markdownoutput_json_dir:outputs/jsonupload_dir:data/uploaded_docslog_dir:outputs/logsdemo_dir:demo_dataparser:prefer_docling:trueprefer_paddleocr:trueimage_lang:chdemo_data/中内置了sample_project_manual.md、sample_invoice.txt、sample_report.pdf、sample_receipt.png和sample_receipt.png.gt.txt。这样设计可以保证项目第一次运行时不依赖外部数据同时覆盖 Markdown、TXT、PDF 和图片几种常见输入类型。五、运行结果与后续 AI 接入当前项目运行python run_demo.py后会在日志中保存摘要outputs/logs/last_run_summary.json示例摘要如下{total_files:4,items:[{source:sample_invoice.txt,engine:builtin_text_reader},{source:sample_project_manual.md,engine:builtin_text_reader},{source:sample_receipt.png,engine:sidecar_ocr_demo},{source:sample_report.pdf,engine:pymupdf_fallback}]}Markdown 导出目录中可以看到sample_invoice.md、sample_project_manual.md、sample_receipt.md和sample_report.md。每个 Markdown 文件都包含解析信息、正文内容和元数据。比如图片票据解析结果会写明当前使用的是sidecar_ocr_demoPDF 示例会写明当前使用的是pymupdf_fallback。这能让用户清楚知道当前环境用了哪个解析引擎。文档解析系统本身可以独立使用但它更大的价值是成为后续 AI 项目的数据入口。以 RAG 知识库为例本项目导出的 Markdown 可以继续进入以下流程Markdown 文档 ↓ 按标题或段落切分 ↓ Embedding 向量化 ↓ 写入 Chroma / FAISS / Milvus ↓ 问题检索 Top-K 片段 ↓ 大模型生成回答 ↓ 返回答案与来源JSON 结果则适合做信息抽取和系统集成。比如票据识别项目可以把 JSON 写入数据库合同解析项目可以把 JSON 中的字段传给审核规则资料归档项目可以把文件名、解析引擎、解析时间、正文摘要写入检索系统。相比单纯输出 TXTMarkdown 和 JSON 的可复用性更强。六、业务落地、扩展方向与常见问题真实 PDF 和图片的复杂度通常比 Demo 高得多。合同可能有页眉页脚、印章、水印和手写批注论文可能有双栏排版、公式、图表和参考文献票据图片可能存在倾斜、反光、模糊和遮挡。项目要从演示走向业务首先要做解析质量评估不能只看是否“有文字输出”还要看标题层级是否正确、表格是否被拆乱、页码和页眉是否误入正文、OCR 是否把相似字符识别错。其次是文件安全。企业文档解析系统通常会处理合同、报价单、身份证明和财务凭证等敏感资料。上传目录需要权限控制输出目录也不能公开暴露。日志中尽量不要记录完整正文可以只记录文件哈希、解析耗时和错误类型。再次是大文件处理。几十页 PDF 可以同步解析几百页 PDF 就不适合阻塞 HTTP 请求。生产环境应该使用后台任务把上传和解析拆成两个步骤上传后返回任务 ID后台解析完成后前端再查询状态。如果要继续二次开发可以增加用户和历史记录为每个用户保存上传文件、解析结果和下载记录也可以增加字段抽取从发票中抽取金额、日期、编号从合同中抽取甲方、乙方、期限和金额还可以把 Markdown 结果切分后写入向量数据库提供一个问答页面把系统升级为“文档解析 知识库问答”。PDF 没有文字输出怎么办先确认 PDF 是否有文本层。很多扫描件 PDF 本质上是一张张图片普通文本抽取工具读不到文字是正常现象。可以先复制 PDF 中的文字如果复制出来为空或乱码说明需要 OCR。此时建议安装 Docling 或 PaddleOCR再重新解析。PaddleOCR 安装失败怎么办PaddleOCR 依赖 PaddlePaddle而 PaddlePaddle 与系统、Python 版本、CPU/GPU 环境相关。如果复制了不适合自己环境的安装命令就可能出现依赖冲突。因此项目没有把 PaddlePaddle 强行写入轻量依赖而是单独放到增强依赖说明中。建议先跑通基础 Demo再根据自己的机器环境安装 OCR 后端。中文路径或空格路径会影响运行吗项目中使用pathlib.Path处理路径并通过safe_filename对上传文件名做清洗可以减少这类问题。但在 Windows 环境下仍然建议把项目放在较短、稳定的英文目录中避免特殊符号或过深路径。输出结果看起来不够“智能”怎么办文档解析系统的目标不是替代大模型生成内容而是把原始文件转换成可复用数据。对于复杂合同、论文和票据解析之后通常还需要字段抽取、规则校验、人工复核或大模型理解。本文项目提供的是前置数据层后续可以继续接入信息抽取、知识库问答和自动报告生成。Web 页面可以打开但上传后没有结果怎么办可以先运行python run_demo.py验证后端解析流程是否正常再访问/api/health检查服务状态。如果 Demo 能跑通而上传失败多半是文件类型不在支持范围内或者上传文件过大。生产部署时可以增加文件大小限制、上传进度提示和后台任务队列。七、总结本文实现了一个基于 Docling PaddleOCR 思路的 PDF/图片文档智能解析系统。项目没有停留在工具介绍层面而是提供了完整源码结构、Web 页面、示例数据、导出结果和运行截图。为了提高可运行性系统默认提供轻量 fallback保证即使没有安装大依赖也能完成 Demo如果安装 Docling 和 PaddleOCR则可以增强 PDF 版面理解和真实图片 OCR 能力。相比直接做一个知识库问答页面这个项目更靠近真实 AI 工程的基础层先把 PDF、图片和普通文本变成可复用的 Markdown/JSON再交给 RAG、字段抽取、摘要生成或审核系统。这个路线既适合学习文档智能处理也适合继续扩展成企业资料归档、票据识别、合同解析和知识库预处理平台。