# pdf2md **Repository Path**: amy_lin/pdf2md ## Basic Information - **Project Name**: pdf2md - **Description**: 用Foxit SDK 实现的超好用的pdf2md转换工具 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2026-03-01 - **Last Updated**: 2026-03-02 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # PDF2MD — PDF 转 Markdown 服务 基于 **Foxit PDF SDK (Python)** + **FastAPI** 构建的 PDF 转 Markdown Web 服务。 --- ## 功能特性 - **智能文本提取** — 逐字符获取字体名称、字号、粗体/斜体属性及坐标位置 - **自动标题识别** — 优先使用 PDF 书签(Bookmark)映射标题层级,回退到字号比例启发式算法 - **图片提取** — 自动识别并导出页面中的嵌入图片为 PNG 格式 - **超链接保留** — 识别文本中的 URL 并转换为 Markdown 链接语法 - **目录生成** — 从 PDF 书签树自动生成嵌套 Markdown 目录 - **Web UI** — 支持拖拽上传、实时转换进度、源码/预览双标签切换、一键下载和复制 - **REST API** — 可供其他系统集成调用 --- ## 项目结构 ``` pdf2md_pyweb/ ├── app/ │ ├── __init__.py # 包初始化 │ ├── config.py # SDK License 及目录配置 │ ├── pdf_parser.py # Foxit SDK PDF 解析核心模块 │ ├── md_converter.py # 结构化内容 → Markdown 转换引擎 │ └── main.py # FastAPI 路由与 Web 服务 ├── templates/ │ └── index.html # Web UI 页面 ├── static/ # 静态资源(预留) ├── uploads/ # 上传的 PDF 文件暂存目录(自动创建) ├── output/ # Markdown 输出及提取的图片 │ └── images/ # 提取的图片存放目录 ├── requirements.txt # Python 依赖清单 └── run.py # 服务启动入口 ``` --- ## 环境要求 | 项目 | 要求 | |------|------| | 操作系统 | Windows 10/11 或 Linux | | Python | 3.8 — 3.12 | | Foxit PDF SDK | 通过 pip 安装 `FoxitPDFSDKPython3` | | 内存 | 建议 ≥ 4 GB | --- ## 部署步骤 ### 1. 克隆 / 获取项目 ```bash cd /your/workspace git clone pdf2md_pyweb cd pdf2md_pyweb ``` ### 2. 创建虚拟环境(推荐) ```bash python -m venv venv # Windows venv\Scripts\activate # Linux / macOS source venv/bin/activate ``` ### 3. 安装依赖 ```bash pip install -r requirements.txt ``` 依赖列表: - `FoxitPDFSDKPython3` — Foxit PDF SDK Python 绑定 - `fastapi` — Web 框架 - `uvicorn[standard]` — ASGI 服务器 - `python-multipart` — 文件上传支持 - `Jinja2` — HTML 模板引擎 - `aiofiles` — 异步文件操作 ### 4. 配置 License(如需修改) License 已内置在 `app/config.py` 中。如需更换,编辑该文件或通过环境变量设置: ```bash # Windows PowerShell $env:FOXIT_SN = "your_sn_here" $env:FOXIT_KEY = "your_key_here" # Linux / macOS export FOXIT_SN="your_sn_here" export FOXIT_KEY="your_key_here" ``` ### 5. 启动服务 ```bash python run.py ``` 服务将在 **http://0.0.0.0:8000** 启动。 启动参数可在 `run.py` 中调整: ```python uvicorn.run( "app.main:app", host="0.0.0.0", # 监听地址,0.0.0.0 允许外部访问 port=8000, # 端口号 reload=True, # 开发模式热重载(生产环境建议关闭) ) ``` > **生产环境部署建议:** 将 `reload=True` 改为 `reload=False`,并考虑使用 `workers=4`(多进程)提升并发性能。 --- ## 使用方式 ### 方式一:Web UI 1. 打开浏览器访问 **http://localhost:8000** 2. 将 PDF 文件拖拽到上传区域,或点击选择文件 3. 勾选选项: - ✅ **提取图片** — 是否导出 PDF 中的嵌入图片 - ✅ **生成目录** — 是否从书签生成 Markdown 目录 4. 点击 **「开始转换」** 按钮 5. 转换完成后可: - 在 **「源码」** 标签查看原始 Markdown - 在 **「预览」** 标签查看渲染效果 - 点击 **「下载 .md 文件」** 保存到本地 - 点击 **「复制 Markdown」** 复制到剪贴板 ### 方式二:REST API #### 转换 PDF ```bash curl -X POST http://localhost:8000/api/convert \ -F "file=@/path/to/your/document.pdf" \ -F "include_images=true" \ -F "include_toc=true" ``` **响应示例:** ```json { "success": true, "markdown": "# Document Title\n\n## Chapter 1\n\n...", "filename": "document_1709012345678.md", "download_url": "/api/download/document_1709012345678.md", "stats": { "page_count": 10, "text_blocks": 156, "images_extracted": 3, "links_found": 8, "bookmarks": 12, "parse_time_ms": 450, "convert_time_ms": 23, "title": "Sample Document", "author": "Author Name" } } ``` #### 下载 Markdown 文件 ```bash curl -O http://localhost:8000/api/download/document_1709012345678.md ``` #### 健康检查 ```bash curl http://localhost:8000/api/health # {"status": "ok", "service": "pdf2md"} ``` #### Swagger 文档 FastAPI 自动生成的交互式 API 文档: - Swagger UI: http://localhost:8000/docs - ReDoc: http://localhost:8000/redoc --- ## API 参考 | 方法 | 路径 | 说明 | |------|------|------| | `GET` | `/` | Web UI 页面 | | `POST` | `/api/convert` | 上传 PDF 并转换为 Markdown | | `GET` | `/api/download/{filename}` | 下载已转换的 .md 文件 | | `GET` | `/api/health` | 服务健康检查 | ### `POST /api/convert` 参数 | 参数 | 类型 | 必填 | 默认值 | 说明 | |------|------|------|--------|------| | `file` | File | ✅ | — | PDF 文件 | | `include_images` | bool | — | `true` | 是否提取图片 | | `include_toc` | bool | — | `true` | 是否生成目录 | --- ## 核心技术原理 ### PDF 解析流程 ``` PDF 文件 │ ▼ Library.Initialize(sn, key) ← SDK 初始化 │ ▼ PDFDoc(path) → doc.Load() ← 加载文档 │ ├── Metadata → 标题、作者 ├── Bookmark → 目录树 │ ▼ 遍历每一页 PDFPage: │ ├── TextPage(page) → GetCharInfo() 逐字符提取 │ ├── font_name, font_size → 标题检测 │ ├── is_bold, is_italic → 样式识别 │ └── char_box (x,y,w,h) → 布局排序 │ ├── GraphicsObjects → ImageObject → Bitmap → PNG │ └── PageTextLinks → URL + 文本范围 ``` ### 标题识别策略 1. **书签优先**:如果 PDF 包含书签(Bookmark),将书签标题与页面文本块进行模糊匹配,匹配到的文本块标记为对应层级的标题 2. **字号启发式**:统计全文档字号分布,找到"正文字号"(占字符总数最多的字号),然后按比例映射标题层级: | 字号/正文字号 比值 | 标题层级 | |-------------------|----------| | ≥ 2.0 | H1 | | ≥ 1.7 | H2 | | ≥ 1.4 | H3 | | ≥ 1.2(粗体) | H4 | | ≥ 1.05(粗体) | H5 | | = 1.0(粗体) | H6 | --- ## 常见问题 ### Q: SDK 初始化失败怎么办? 检查 `app/config.py` 中的 `FOXIT_SN` 和 `FOXIT_KEY` 是否正确。错误码含义: - `e_ErrInvalidLicense` — License 无效或已过期 - `e_ErrParam` — 参数格式错误 ### Q: 中文 PDF 乱码? Foxit SDK 内置了中文字体支持,通常不会出现乱码。如遇到问题,确保系统安装了中文字体。 ### Q: 图片没有被提取? - 确认勾选了「提取图片」选项 - 部分 PDF 中的图片可能以矢量路径(PathObject)形式存在,而非位图(ImageObject),这类图片暂不支持提取 - 检查 `output/images/` 目录是否有写入权限 ### Q: 转换速度慢? - PDF 页数多时解析耗时较长,主要瓶颈在逐字符信息提取 - 如不需要精确的文本样式信息,可修改 `pdf_parser.py` 使用 `TextPage.GetText()` 替代逐字符遍历 - 生产环境建议关闭 `reload` 模式 ### Q: 如何处理加密 PDF? 当前版本不支持带密码的 PDF 文件,上传加密文件会返回 400 错误提示。 --- ## License 本项目使用 Foxit PDF SDK,需遵守 Foxit 的商用许可协议。