一个智能的 PDF 批量处理工具(Web 版),能够:
- 自动识别 PDF 类型:纯文本、扫描件、混合型 —— 三种策略各取所长
- 智能选择提取方案:纯文本用 PyMuPDF 直接读,扫描件走 MinerU OCR
- Web 端操作:浏览器拖拽上传 → 实时进度查看 → 一键下载 CSV
- 任务持久化:基于 PocketBase,断电/重启不丢任务记录
| 场景 | 传统方案 | 本工具 |
|---|---|---|
| 纯文本 PDF | 用 OCR → 错误率高、速度慢 | PyMuPDF 直接提取 ✅ 快速准确 |
| 扫描件 PDF | 直接读文字 → 读不到内容 | MinerU OCR ✅ 高质量识别 |
| 混合型 PDF | 统一方案 → 总有一方出问题 | 智能分流处理 ✅ 各取所长 |
┌──────────────────────────────────────────────────────────────────┐
│ 浏览器 (前端) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 上传面板 │ 进度看板(含类型分布) │ 结果展示 & CSV 下载 │ │
│ └──────────────────────┬──────────────────────────────────┘ │
└─────────────────────────│───────────────────────────────────────┘
│ HTTP / SSE
▼
┌──────────────────────────────────────────────────────────────────┐
│ Flask Web 服务 (端口 5000) │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌────────────────────┐ │
│ │ 文件上传 API │ │ SSE 实时推送 │ │ CSV 下载 / 取消 │ │
│ └──────┬───────┘ └──────┬───────┘ └────────▲───────────┘ │
│ │ │ │ │
│ └────────┬────────┘ │ │
│ ▼ │ │
│ ┌─────────────────────┐ │ │
│ │ 后台处理线程池 │────────────────┘ │
│ │ 类型检测 → 提取 → CSV │ │
│ └──────────┬──────────┘ │
└─────────────────────│───────────────────────────────────────────┘
│ 读写
▼
┌──────────────────────────────────────────────────────────────────┐
│ PocketBase (端口 8090) — 数据 & 文件存储 │
│ │
│ ┌─────────────────────┐ ┌──────────────────────────┐ │
│ │ tasks 集合 │ 1∶N │ pdf_files 集合 │ │
│ │ · status │─────│· task (relation) │ │
│ │ · total_files │ │· pdf_file (文件字段) │ │
│ │ · result_csv (文件) │ │· filename / content │ │
│ │ · progress ... │ │· pdf_type │ │
│ └─────────────────────┘ └──────────────────────────┘ │
└──────────────────────────────────────────────────────────────────┘
│ (仅扫描件/混合型)
▼
┌──────────────────────────────────────┐
│ MinerU API (外部服务) │
│ AI/OCR 公式识别 / 表格识别 │
└──────────────────────────────────────┘
| 模块 | 文件 | 职责 |
|---|---|---|
| Web 入口 | web/app.py |
Flask 路由、SSE 推送、后台任务编排 |
| PB 客户端 | web/pb_client.py |
PocketBase 认证、CRUD、文件上传下载 |
| 前端页面 | web/templates/index.html |
上传界面 + 实时进度 + 类型分布展示 |
| 样式表 | web/static/style.css |
响应式布局、类型统计卡片样式 |
| 类型检测 | pdf_detector.py |
分析每页文本/图像占比,判断 PDF 类型 |
| 文本提取 | pdf_processor.py |
PyMuPDF 本地提取 + MinerU OCR 调度 |
| OCR 客户端 | mineru_client.py |
MinerU 异步 API 封装 |
Docker 镜像内置 PocketBase + Flask,启动即可使用。
# 1. 克隆项目
git clone https://github.com/AleWarriorPrior/PDF-all-Processor.git
cd PDF-Text-Extractor
# 2. 构建镜像(包含 PocketBase v0.36.x)
docker build -t pdf-text-extractor .
# 3. 运行容器
docker run -d \
--name pdf-extractor \
-p 5000:5000 \
-p 8090:8090 \
-e MINERU_API_TOKEN=your_token_here \
-v pdf-extractor-data:/pb_data \
pdf-text-extractor
# 4. 打开浏览器访问
open http://localhost:5000端口说明:
| 端口 | 服务 | 用途 |
|---|---|---|
| 5000 | Flask | Web 前端 + API |
| 8090 | PocketBase | 数据库 + 文件存储 + 管理后台 |
💡 PocketBase 管理后台:
http://<host>:8090/_/(默认账号admin@admin.com/adminadmin123)
| 宿主机系统 | 是否支持 | 说明 |
|---|---|---|
| Ubuntu / Debian | ✅ | 原生支持,docker build && docker run 直接运行 |
| CentOS / RHEL / Fedora | ✅ | 同上,容器内为 Debian,不受主机发行版影响 |
| macOS (Intel / Apple Silicon) | ✅ | 需要 Docker Desktop |
| Windows 10/11 | ✅ | 需要安装 Docker Desktop (WSL2) |
Windows 用户注意: 项目已配置
.gitattributes强制 LF 换行,git clone后直接构建即可。如果遇到脚本执行错误(\r: No such file),请确保使用 Git Bash 或 WSL2 终端执行 docker 命令。
PocketBase 是本项目的必需依赖——用于存储任务记录、上传的 PDF 文件和生成的 CSV 结果。
# 下载 PocketBase(根据你的系统选择)
# macOS (Apple Silicon):
curl -fsSL https://github.com/pocketbase/pocketbase/releases/download/v0.36.8/pocketbase_0.36.8_darwin_arm64.zip -o pb.zip
# macOS (Intel):
curl -fsSL https://github.com/pocketbase/pocketbase/releases/download/v0.36.8/pocketbase_0.36.8_darwin_amd64.zip -o pb.zip
# Linux (x86_64):
curl -fsSL https://github.com/pocketbase/pocketbase/releases/download/v0.36.8/pocketbase_0.36.8_linux_amd64.zip -o pb.zip
# 解压并启动
unzip pb.zip && ./pocketbase serve启动后 PocketBase 运行在
http://127.0.0.1:8090首次启动会引导创建管理员账号。建议使用默认:
- 邮箱:
admin@admin.com- 密码:
adminadmin123
PocketBase 首次启动后需要创建两个数据集合(tasks 和 pdf_files)。
方式 A:通过管理后台手动创建
- 打开
http://127.0.0.1:8090/_/登录 - 左侧菜单 → Collections → 创建以下两个集合:
tasks 集合字段:
| 字段名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| status | text | ✅ | 任务状态:pending / processing / completed / failed |
| total_files | number(int) | ✅ | 总文件数 |
| processed_files | number(int) | ❌ | 已处理数 |
| success_count | number(int) | ❌ | 成功数 |
| failed_count | number(int) | ❌ | 失败数 |
| current_filename | text | ❌ | 当前正在处理的文件名 |
| error_message | text | ❌ | 错误信息 |
| result_csv | file | ❌ | 生成的 CSV 结果文件 |
pdf_files 集合字段:
| 字段名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| task | relation(tasks) | ✅ | 关联的任务(cascadeDelete) |
| filename | text | ✅ | 原始文件名 |
| status | text | ❌ | 处理状态 |
| pdf_type | text | ❌ | 检测结果:text_only / scan_only / mixed |
| content | editor | ❌ | 提取出的文本内容 |
| error_message | text | ❌ | 错误信息 |
| pdf_file | file | ❌ | 上传的 PDF 原始文件 |
⚠️ 注意:创建taskrelation 字段时,必须指定目标 collectionId 为tasks集合的实际 ID。
方式 B:Docker 部署时自动初始化
Docker entrypoint 脚本 (docker-entrypoint.sh) 会在容器首次启动时自动完成:
- 管理员账号创建(或 upsert)
tasks和pdf_files数据集合的创建与字段校验- 不完整旧集合的清理与重建
无需手动操作。
# 1. 克隆项目
git clone https://github.com/AleWarriorPrior/PDF-Text-Extractor.git
cd PDF-Text-Extractor
# 2. 创建虚拟环境
python -m venv venv
source venv/bin/activate # Linux/Mac
# 3. 安装依赖
pip install -r requirements.txt
# 4. 配置环境变量(可选)
cp .env.example .env
# 编辑 .env,填入你的 MinerU Token(扫描件 OCR 需要)
# 5. 启动 Flask
export FLASK_PORT=5002 # 默认 5000,被占用时可改
python web/app.py
# 或使用 nohup 后台运行
# nohup env FLASK_PORT=5002 python web/app.py &启动成功后会看到:
============================================================
📄 PDF Processor Web Service
============================================================
URL: http://127.0.0.1:5002
Debug: False
PocketBase: http://127.0.0.1:8090
============================================================
浏览器打开对应地址即可使用。
如果不需要 Web UI,也可以直接用命令行处理本地 PDF 文件:
python pdf_processor.py --input ./your_pdf_folder -o ./output/result.csv详见下方「CLI 使用指南」。
打开页面 → 拖拽/选择 PDF 文件 → 点击「开始处理」
→ 实时查看进度(含文档类型分布统计) → 处理完成 → 下载 CSV
| 区域 | 功能 |
|---|---|
| 上传区域 | 支持多选、拖拽上传,单文件最大 200MB |
| 进度面板 | SSE 实时推送:已处理/成功/失败计数、当前文件名 |
| 📊 类型分布 | 三栏卡片实时显示纯文本(绿)、扫描件(红)、混合型(橙)数量 |
| 结果区 | 处理完成后显示汇总 + 彩色类型徽章 + CSV 下载按钮 |
| 取消按钮 | 可随时中止正在进行的任务 |
unique_id,source_filename,content,pdf_type
"550e8400-e29b...","合同_2024.pdf","采购合同\n甲方:XX公司\n...",text_only
"a1b2c3d4-e5f6...","发票_扫描件.pdf","发票号码: 12345678\n金额: ¥10,000",scan_only| 变量名 | 说明 | 默认值 | 是否必填 |
|---|---|---|---|
| PB_URL | PocketBase 服务地址 | http://127.0.0.1:8090 |
推荐 |
| PB_ADMIN_EMAIL | PB 管理员邮箱 | admin@admin.com |
PB 默认 |
| PB_ADMIN_PASSWORD | PB 管理员密码 | adminadmin123 |
PB 默认 |
MINERU_API_TOKEN |
MinerU API Token | 无 | 可选(免费 API 无需 Token) |
FLASK_PORT |
Flask 监听端口 | 5000 |
可选 |
FLASK_DEBUG |
Flask 调试模式 | 0 |
可选 |
MAX_CONCURRENT_TASKS |
并发任务数 | 3 |
可选 |
POLL_INTERVAL |
API 轮询间隔(秒) | 2 |
可选 |
TASK_TIMEOUT |
单任务超时时间(秒) | 300 |
可选 |
注意: 免费版 Agent API 无需 Token,但限制文件大小 ≤10MB 且 ≤20 页。 如果需要处理更大文件或更高并发,请申请 Token。
# 健康检查(验证 Flask + PocketBase 连通性)
curl http://localhost:5000/health
# 预期返回: {"status":"ok","pocketbase":"connected"}
# 测试 PDF 类型检测
python pdf_detector.py test_file.pdf
# 测试 MinerU API 连接
python mineru_client.py test_scan.pdf
# CLI 快速预览一批文件的类型分布
python pdf_processor.py --input ./test_pdfs --detect-onlypdf-processor-all/
├── web/
│ ├── app.py # Flask Web 入口(路由/SSE/后台任务)
│ ├── pb_client.py # PocketBase 客户端封装
│ ├── templates/
│ │ └── index.html # 前端单页(上传+进度+结果)
│ └── static/
│ └── style.css # 样式表(响应式布局)
├── pdf_processor.py # 核心处理逻辑(PyMuPDF + MinerU)
├── pdf_detector.py # PDF 类型智能检测模块
├── mineru_client.py # MinerU 异步 OCR API 客户端
├── requirements.txt # Python 依赖清单
├── Dockerfile # Docker 构建文件(含 PB + Flask)
├── docker-entrypoint.sh # 容器启动脚本(初始化 PB + 集合)
├── .env.example # 环境变量模板
└── README.md # 本文件
# docker-compose.yml
version: "3.8"
services:
pdf-extractor:
build: .
container_name: pdf-extractor
ports:
- "5000:5000" # Flask Web
- "8090:8090" # PocketBase
environment:
- MINERU_API_TOKEN=${MINERU_API_TOKEN}
- FLASK_PORT=5000
- PB_ADMIN_EMAIL=admin@admin.com
- PB_ADMIN_PASSWORD=your_secure_password_here
volumes:
- pb_data:/pb_data # PB 数据持久化
- uploads:/app/web/uploads # 上传文件临时存储
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:5000/health"]
interval: 30s
timeout: 10s
retries: 3
volumes:
pb_data:
uploads:# 一键启动
docker compose up -d- PocketBase v0.36.x(或让 Docker 自动安装)
- Python 3.9+ 环境(Docker 部署则无需单独安装)
- 开放端口:5000(Flask)、8090(PB)
- 配置
.env文件(尤其是 PB 连接信息和 MinerU Token) - 反向代理(Nginx/Caddy):将 80/443 转发到 5000
- 如果需要从外网访问 PB 管理后台,也转发 8090(生产环境建议限制 IP)
- 配置备份策略:pb_data 目录(SQLite 数据库 + 存储的文件)
- 监控日志和错误告警
server {
listen 80;
server_name your-domain.com;
# Flask Web 前端
location / {
proxy_pass http://127.0.0.1:5000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
# SSE 长连接关键配置
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 3600s;
chunked_transfer_encoding on;
}
# PocketBase(可选,限制内网/IP白名单访问)
location /pb-admin/ {
proxy_pass http://127.0.0.1:8090/_/;
allow your_trusted_ip;
deny all;
}
}- 控制并发数:建议 2-5 个并发,避免触发 MinerU API 限频
- 大文件优先:先处理大的扫描件,小文件后处理
- PB 文件大小限制:默认 5MB,本项目已调整为 200MB(通过 PATCH 单独设置 maxSize)
- 内存监控:大量 PDF 同时处理会占用较多内存
- 磁盘空间:PB 会存储原始 PDF 和 CSV,定期清理已完成的历史任务
此模式绕过 PocketBase 和 Flask,直接在本地处理。
# 处理单个目录中的所有 PDF
python pdf_processor.py --input /path/to/pdfs
# 处理指定的多个文件
python pdf_processor.py --input file1.pdf file2.pdf file3.pdf
# 使用 MinerU API Token
python pdf_processor.py --input ./pdfs --token YOUR_TOKEN
# 自定义输出路径
python pdf_processor.py --input ./pdfs -o ./results/my_data.csv
# 仅检测 PDF 类型(不实际提取)
python pdf_processor.py --input ./pdfs --detect-only
# 显示详细日志
python pdf_processor.py --input ./pdfs --verboseA: PocketBase 是一个嵌入式 Go 后端,内建 SQLite 数据库 + 文件存储 + RESTful API + 实时订阅。本项目用它来:
- 存储任务状态和处理进度
- 存储上传的 PDF 原始文件和生成的 CSV 结果
- 提供关系型查询(任务 ↔ 文件的 1:N 关系)
- 支持断点续查历史任务记录
它比 PostgreSQL + MinIO + Redis 的组合轻量得多,适合中小规模部署。
A: Web 模式不行——Flask 层强依赖 PB 做数据持久化和文件存储。但 CLI 模式完全不依赖 PB,可以直接 python pdf_processor.py --input ... 运行。
A: 纯文本 PDF 本身包含可提取的文本层,用 OCR 反而可能引入错误识别。PyMuPDF 直接读取文本层是 100% 准确的。
A: Agent 轻量 API 免 Token 但限制:文件 ≤10MB,页数 ≤20 页。超过此限制需使用精准 API(需要 Token)。
A: 单个文件失败不影响其他文件。失败的文件在 CSV 中会有 error 列标注原因。可以单独重试。
A: CSV 输出后可以用 Logstash、Filebeat 或自定义脚本导入 ES。后续可以考虑增加直连 ES 的功能。
A: 所有数据都在 pb_data 目录下的 SQLite 文件中。定时备份此目录即可。Docker 部署时建议挂载命名卷(volume)。
- ✅ 全新 Web 界面:Flask + SSE 实时进度推送
- ✅ 引入 PocketBase:任务持久化、文件存储、历史查询
- ✅ Docker 一键部署:镜像内置 PocketBase + Flask
- ✅ PDF 类型分布可视化:前端三栏卡片 + 结果徽章
- ✅ SSE 实时进度:无刷新更新,支持取消任务
- ✅ 健康检查端点:
/health验证 PB 连通性 - ✅ Nginx SSE 适配:提供反向代理参考配置
- ✅ 初始版本发布(CLI 模式)
- ✅ 支持三种 PDF 类型智能检测
- ✅ PyMuPDF + MinerU 双引擎
- ✅ 异步批量处理
- ✅ 详细统计报告
由资深开发工程师设计并实现,专注于代码质量和生产可用性。
MIT License