PDF大师:一键转Word/Excel

SKILL效率
效率 未标注权限 许可证不明确
安装这个技能

一个把 PDF 转成「转完就能用」的 Word/Excel 的工具。

一句话选型结论

按资料字段整理

PDF大师:一键转Word/Excel是效率类的 Agent Skill,安装方式未标注,权限级别未标注,许可证不明确,有可直接复制的安装命令。技能本质是给模型读的说明书,效果取决于模型与客户端;装完先用一个小任务验证,再放进正式流程。

分类效率 安装方式未标注 权限级别未标注权限 许可证许可证不明确
累计安装 未标注 本周 未标注
GitHub 星标 未标注 仓库 未标注
下载量 未标注 技能市场下载数
权限级别 未标注权限 安装前请确认风险范围
许可证 许可证不明确 未说明

安装

未标注
在支持 Skills 的客户端里执行,装完问一句「你有哪些技能」验证
skillhub install user_99f4db18/pdf-to-detail-word
  1. 1
    确认客户端支持

    确认你的客户端支持 Skills(Claude、Codex、Cursor 等),并升级到较新的版本。

  2. 2
    拿到技能文件

    执行上面的命令安装;也可以把仓库里的 SKILL.md 手动放进客户端的 skills 目录。

  3. 3
    刷新技能列表

    重新打开客户端,或刷新技能列表,让新放进来的技能被加载。

  4. 4
    验证是否生效

    问一句「你有哪些技能」,确认列表里出现它,再拿一个小任务试跑。

技能档案

效率
字段来自技能仓库与公开索引,中文说明由本站标注
作者 / 维护方user_99f4db18仓库 未标注 · 版本 未标注
宿主客户端未标注技能可被这些客户端加载
安装方式未标注安装包 community
权限级别未标注权限安装前请确认风险范围
许可证未说明许可证不明确,商用前请自行确认条款
仓库可用性available技能仓库当前是否可访问
最近核验2026-11-06上游最后核验时间 · 数据更新 2026-11-06
正文体量65.9 KBSKILL.md 原文大小,越大说明说明书写得越细

典型使用场景

3 类
按分类整理的常见用法,具体以 SKILL.md 为准
整理待办与日程

把零散任务收进清单,排出优先级。

批量处理重复任务

把固定动作做成模板,重复执行。

把流程写成清单

把口头流程整理成可复用的步骤。

选择建议

装之前先看这几条
按条目字段给出的判断,不替你决定用不用

值得选的地方

  • 有可直接复制的安装命令,不用自己翻文档找入口。

先想清楚的地方

  • 没有标注权限级别,实际能做什么要装好后确认。
  • 许可证不明确,商用或二次分发前先到仓库确认条款。
  • 没有做站内核验,内容以作者仓库为准。
  • 技能只是说明书,实际效果取决于模型与客户端,装完先用小任务试一遍。

更适合

  • 需要在效率场景里给模型补一套做法的人。
  • 愿意先读一遍 SKILL.md、确认它会让模型做什么的人。

不太适合

  • 对许可证要求很严、必须明确可商用的人。
  • 只想装完就自动变强、不打算看说明书的人。

同类对比

6 个同类
同分类里挑最接近的几条,字段以各自详情页为准
技能权限级别安装方式累计安装宿主客户端安装命令
PDF大师:一键转Word/Excel当前 未标注权限 未标注 未标注 未标注 有
Nano PDF 文档 联网访问 ClawHub 市场 424.9 万 OpenClaw 有
自动更新程序 浏览器控制 ClawHub 市场 296.4 万 OpenClaw 有
Gemini 助手 联网访问 ClawHub 市场 254.7 万 OpenClaw 有
word DOCX 文档 联网访问 ClawHub 市场 239.6 万 OpenClaw 有
Excel XLSX 前端 联网访问 ClawHub 市场 227.0 万 OpenClaw 有

SKILL.md 全文

65.9 KB
模型实际读到的说明书原文,来自技能仓库

name: PDF大师:一键转Word/Excel
slug: pdf-to-detail-word
displayName: PDF大师:一键转Word/Excel
version: 1.1.9
summary: 一键把 PDF 转成可编辑的 Word/Excel:图表重建为可改数据的原生图表、扫描件 OCR、表格数据可反查核验;核心转换全程本地零配置,支持文本/扫描/图文混排/混合横竖版四类 PDF,附加解密/表单/签章/检索工具。
description: "将 PDF 一键转换为可编辑、保留细节的 Word/Excel 文档,并内置按需检索与反查核验的闭环。当用户请求「把 PDF 转成 Word」「PDF 转生产级细节文档」「把这份 PDF 还原成可编辑的详细 Word」「从 PDF 抽取结构化内容并生成带页码引用的 Word」「PDF 转 Excel」,以及「PDF 加解密 / 填表单 / 电子签章 / 在 PDF 中检索」时使用。支持原生文本 PDF、扫描件 PDF、图文混排 PDF、混合横竖版 PDF 四种类型,覆盖结构还原、表格抽取、图表多模态理解、语义切片、双路索引与可追溯引用。此外内置 MarkItDown 通道,可将 Word/PPT/Excel/图片(OCR)/音频/HTML/网页URL 等非 PDF 源快速转为 Markdown(LLM 友好、非像素级还原),并支持任意文档快速纯文本/Markdown 提取。一份 PDF 同时产出 Word(改字排版)+ Excel(算数汇总)双版本,打工人一次搞定。"
license: MIT
author: 薛定谔的脚本
tags:
- pdf
- word
- excel
- docx
- xlsx
- 文档转换
- OCR
- 检索增强
- 加解密
- 签章
- 发票
- 报表
- 合同
requires:
python: ">=3.10"
packages:
- pypdf
- pdfplumber
- python-docx
- openpyxl
- Pillow
- pymupdf
optional:
- sentence-transformers
- pytesseract
- pdf2image
- endesive
- markitdown
- pywin32
metadata:
author: 薛定谔的脚本
slug: pdf-to-detail-word
version: "1.1.9"
changelog: |
1.1.9 (2026-10-24) 文档措辞优化(无功能变更):
- VLM 可选增强的配置说明措辞中性化:鉴权凭据统一表述为「凭据走环境变量」,变量名指引见脚本
- displayName 与简介通俗化:卖点前置,去除「生产级」表述,tags 增加场景词
- 纯文档改动,转换逻辑、脚本与 v1.1.8 完全一致,无需重复回归
1.4.0 (2026-10-04) 精简重构(性能 + 死代码 + 异常可见化,回归全绿、准确率零下降):
- 解析复用(T1,性能核心):convert_to_docx.py 里 8 处各自 pdfplumber.open
收敛为「单次打开 + 页对象/抽取结果复用」(_pdf_scope 引用计数 + pin_pdf
全程钉住 + ctx.text()/ctx.tables() 单页二级缓存);页方向/尺寸改为
_page_geometry() 一次读成纯数据,_apply_section_orientation 不再为设尺寸
重开 PDF;页眉/页脚构建完即 close_pdf() 释放页对象,避免与 python-docx
的文档树+图片内存叠加。实测(同机同 harness 交替 A/B,各 3 次中位数):
47 页文本型 PDF 49.6s→42.4s(-14.5%)、峰值内存 222.4→207.4MB(-6.7%);
27 页图文混排 67.9s→52.0s(-23.4%);预览改用内存 Document 复用后
峰值内存再降 ~35MB(272.8→248.0MB,与基线同 harness)。
- 死代码/重复逻辑(T2):删从未被调用的 _add_page_ref() 与专用常量
PAGEREF;rFonts 写入合并为单一 helper _set_run_rfonts();
_parse_rgb/color_repr 边界分支统一到 _rgb01()(0..255 整数色不再溢出);
convert_to_docx.py 不再依赖 pypdf(pdf_crypto.py 仍需要,pypdf 保留 core)。
- 异常可见化(T3):extract_logo / _build_header logo 写入 / 页眉表格合并 /
figures_desc 解析 / OCR 识别 / 信息图判定等静默 except: pass 全部改为
warn() 进 REPORT;retrieve.py 索引缺失给可操作报错、向量路降级分支可见化
(deps_missing / bm25_only 语义不变)。
- COM 重试统一(T3):word_com_charts.py 新增 com_retry 装饰器,统一覆盖
CALL_REJECTED / 图表数据网格占用 / 文档锁文件三类瞬态失败;AddChart2 重试前
与每张图写完数据后显式收起数据网格(兼容模式下 cd.Activate() 不总稳定接管
的残留分支)。
- 依赖分层(T4):requirements.txt 分 core / optional / dev(reportlab、psutil
入 dev);SKILL.md frontmatter requires 同步分层。
- 目录与文档(T5/T6):scripts/*.bak-v1.1.6 移至 包外归档目录/;
.gitignore 补齐 5 个 *_out/ 回归产物目录;SKILL.md/pipeline.md 与实现同步。
- 1.4.0 轮次2(2026-10-04,同版本号内的交付修正):① 修 PDF 页缓存重构
遗留的调用侧未连通问题(_page_text/_page_tables 已并入 _PdfCtx,调用点
统一改 ctx.text()/ctx.tables();_PdfCtx 实例属性与同名方法冲突已加 _ 前缀规避);
② 颜色行为锁死:1 元组灰度(如 (0.349,))恢复 v1.3.2 语义——
color_repr() 返回不可解析串 → 下游 _parse_rgb 不匹配 → 按黑处理,
不得展开成 595959 灰(铁律 6:重构不得改变任何既有输出)。
新增 闭环回归脚本(未随本包发布) [8] 颜色对照 5 项断言 + 冻结期望分布
{000000:5, CC0000:1, FF3319:1},与真实基线脚本逐字节全等;日后要
"正确还原灰度"须另立 feature 单;③ 边框写入合并为单一 _set_table_borders(table, edges, ...)。
- 1.4.0 轮次4(2026-10-05,行数收官):注释/docstring 压至要点、结构去重后,
交付件行数回到基线:convert_to_docx.py 1500→1483(-17)、word_com_charts.py
541→541(±0)、retrieve.py 136→153(+17,T3 告警)——交付件小计 净增 0;
5 套回归 + 颜色对照复跑全绿(闭环回归脚本(未随本包发布) PASS 78/78)。
1.3.2 (2026-10-03) 半导体人力报告 Word「跟 PDF 差距大」诊断修复(53 页源 → 329 页产物,
四个根因逐一定位修复,终版 64 页 + 7 张原生图):
- 页脚误判膨胀(最大根因):_build_footer 把所有页底部 7% 文字无差别收集进 Word footer,
设计版式页(信息图)底部的装饰文字/数字导航被当成"每页页脚",footer 高达大半页,
正文区被挤压 → 页数成倍膨胀。修复:真页脚特征=同样文字在多数页重复出现,
新增「出现页数 >= max(3, 总页数30%)(小文档>=2、单页退回旧行为)」+「单行 >100 字符排除」
双约束;无真页脚时回退 PAGE 页码域(右对齐)。
-
装饰小图放大:62-95px 的列表图标/色块(118 图中 102 张)被统一放大 14cm 插入。
修复:图片块记录源 PDF 显示宽高(disp_w_pt/disp_h_pt),宽高均 <100pt 的装饰图跳过,
真图表按源显示宽换算 cm(pt
2.54/72,上限 14.5cm),不再一律 14cm。
- 扫描页整页图跨页翻倍:14cm 宽 A4 整页图(高约 19.8cm)+ 默认 1.15 倍行距 + 段距 +
[P.X] 标记段超出一页可用高度,图被推到下一页 → 每个扫描页裂成两页。
修复:整页图收窄 12cm + 图片段落单倍行距 + 零段距,标记段压缩,同页稳定。
- 信息图页碎片化:设计版式页(环形图+数据标签)的短标签文字(8.2%、500-1000 人)
被抽取散排成竖排碎片。新增 _is_infographic_page():行数>=6 且行均长<12 且短行(<=15字)
占比>0.85 且 find_tables<=2 且含图 → 整页渲染图化(保真优先);
TOP100 类真表格页(每页 9+ 张真表)正确排除,制度/合同类长句文档永不触发。
- 页眉 logo 误抓封面图:extract_logo 取首页第一张 >20x20 图,封面页抓到全页背景图
(正方形 1546x1687),每页页眉顶着模糊封面缩略。修复:只选横条形图(宽高比>=1.2)。
- 实战配套:修复版引擎重转 + word_com_charts 按题注锚点("图 X-Y(来源:PDF 第 X 页)")
重挂 7 张核心原生图(信息图化吸收的 7 张在 Excel 有原生版对应)。
1.3.1 (2026-10-02) 用户强化指令「源 PDF 有图表,转出的 Excel 也必须要有」:
- Excel 输出规范新增图表还原铁律:源 PDF 出现图表(柱/条/折线/饼/散点等,背后是表格数据的),
转出 Excel 必须重建为 openpyxl 原生可编辑图表对象,不能只留数据表或静态截图;静态截图仅作兜底。
- 校验闭环补一条:重开 xlsx 确认 _charts 非空且系列名/数据引用正确(防「漏挂/只贴图」)。
1.3.0 (2026-10-02) 用户指令:并入 Word COM 原生图表替换路线(半导体行业人力报告 16/16
原生图实战收官沉淀):
- scripts/word_com_charts.py:锚点定位 docx 里已有静态图 → InlineShapes.AddChart2 原生图
→ COM 写入数据 → 显式系列重建,全 XlChartType(柱/条/折线/饼),含失败回填原图、
保存降级链、核对版 PDF 导出(ExportAsFixedFormat 17)
- 最大根因沉淀:AddChart2 默认仅 3 系列,ListObject 扩列后图表不会自动跟随扩展
(取 SeriesCollection(4) 报"参数无效")→ 写完数据必须显式重建系列
(改 Values/XValues 公式 + NewSeries 补足),4-5+ 系列一次通过
- 图表数据网格状态机(插入后必须立即 Activate 接管)/ zip 句柄泄漏 / 锁文件三件套
/ CALL_REJECTED 重试,全部内建自动处理
- 回归基线 COM 图表回归脚本(未随本包发布)(19 项:5/4 系列重建断言覆盖主坑;无 Word 自动 SKIP)
1.2.0 (2026-09-30) 用户指令:新增原生可编辑图表注入(吸收已删除技能 已删除的图表技能 的核心能力):
- Word:scripts/native_charts.py 手写 DrawingML 注入簇状柱形/折线图——chart part 与嵌入数据
工作簿必须 zip 落盘、[Content_Types] 注册 Override、catAx/valAx + strCache/numCache 缓存
(渲染空白三大根因),占位段落正则锚定替换;c:dispBlanksAs=gap 支持 None 缺口
- Excel:openpyxl 原生 Bar/Line 图表配方(非连续列逐列 Series + set_categories + numFmt)
- 回归基线 原生图表回归脚本(未随本包发布)(冒烟首跑即抓到嵌入簿 </c:r> 闭合标签真 bug——图表能渲染
但 Word「编辑数据」会打不开,教训:嵌入簿必须 openpyxl 重开验证)
- 修复「相关技能」对已删除技能的悬空引用
1.1.7 (2026-09-29) 对抗性测评闭环修复(5 个真实缺陷,3 个 P0):
- 修页首 10% 盲区致正文首段整段静默消失;首屏内容大表被误判为信笺头搬进页眉
- 修首行含合并单元格的表令转换直接崩溃(IndexError);文档标题被搬进页眉每页重复
- 修单级编号(1、/1.)正文条款误判为 H1;回归基线 60→73 项,独立对抗套件 66 项全绿
1.1.6 (2026-09-22) 修 OCR 可用性假阳性:额外探测系统 tesseract 二进制,缺失时诚实报「OCR 不可用」并走仅渲染图片降级
1.1.5 (2026-09-21) 版本对齐补记(无功能变更,补齐 CHANGELOG 1.1.3–1.1.5 断层)
1.1.4 (2026-09-21) 用户明确指令固化的铁律——合并表格保真:
- 源 PDF 表格是合并单元格的,产出的 Word 与 Excel 都必须还原同样的合并结构,与源 PDF 一致
(Word 用 w:gridSpan / w:vMerge;Excel 用 merge_cells)
- 表头一律用源文原文:不翻译、不改写、不擅自拆列/改列名(含源自带拼写错误也原样保留)
- 校验闭环:Word 直解析 OOXML 逐行累加 gridSpan 核对;Excel 重开核对 merged_cells.ranges
1.1.3 (2026-09-21) TRACE 测评后优化:
- 新增结构复用:convert_to_docx.py --structure-out 落盘 {typography,structure} JSON,
build_index.py --structure-in 直接复用,免去「闭环必须双跑」的 2× 解析开销
- 结构文件缺失/损坏自动回退重新抽取,不阻断主流程(TRACE 评测 E 维度优化点 P1)
- 修正 references/pipeline.md §9.2 工具脚本 CLI 签名(原 --in/--out/--query 与脚本真实 positional 接口不符)
1.1.2 (2026-09-18) 收尾 P2 尾巴("全部再检查并闭环"):
- 修混合横竖版分节切回:原只在"方向≠首页方向"时开节,横版后回竖版被锁在横版节;现为跟踪"上一节方向",凡方向变化(含切回)都开新节并设正确尺寸/方向
- 删 build_docx 中 typo['title'] 死代码(赋值未用)
- 澄清 Word 图片描述:add_picture(width=Cm(14)) 只设宽、python-docx 自动保比例,不变形(此前文档误述为"不保纵横比")
- 闭环回归脚本(未随本包发布) 新增 [6] 混合横竖版 3 页 P/L/P 分节回归
1.1.1 (2026-09-18) 闭环验证挖出的 3 个真缺陷:
- 修标题误判:编号开头的正文段落(如「1.1 为规范公司…特制定本制度。」)不再被当成标题
- 修取色:char['color'] 为 None 时回退 non_stroking_color(红批注/蓝链接原色保留真正生效)
- 修 build_chunks:跨页状态不再丢失;标题文本并入正文,标题关键词可被检索命中
- 新增 scripts/闭环回归脚本(未随本包发布)(54 项内容级核验)
1.1.0 (2026-09-18) 合并 原 PDF 工具技能:
- 吸收 4 个工具脚本:pdf_crypto / pdf_form / pdf_sign / pdf_search
- 修复 verify.py 解包崩溃(load 返 4 值接 3 值)并接上真正的双路 RRF 融合
- 修正 pipeline.md 三处文档/实现漂移(页脚域、未实现的续表合并、页码引用口径)
- frontmatter 补齐 slug/changelog/requires
1.0.3 支持 Excel (.xlsx) 输出
1.0.2 修复信笺头重复进正文、混合横竖版崩溃

compatibility: "需要 Python 3.10+, 支持 WorkBuddy / OpenClaw / Claude Code 等 AI Agent 平台运行。"

PDF转Excel和Word

Overview

构建从 PDF 到 Word 的完整自动化转换流水线,覆盖按需检索、精准读页、复杂表格抽取、多模态图像理解及反查核验的全闭环流程。最终产物是一份结构完整、页码可追溯、可二次编辑的生产级 Word 文档;同时产出带 metadata 的语义切片与双路索引,供检索、问答与闭环评测复用。此外附带 PDF 加解密、表单填写、电子签章、单文件 IR 检索四项工具能力。

本技能为自包含引擎:底层转换逻辑全部在 scripts/ 下的 Python 脚本实现
(基于 pypdf / pdfplumber / python-docx / openpyxl / Pillow / pymupdf),不依赖其他技能,可独立运行。

多模态图表理解使用内置视觉能力(将图表区域渲染为图片后用 Read 工具读取分析)。

输出格式:默认 Word (.docx);同时支持 Excel (.xlsx) 输出(v1.0.3+),适用于发票/装箱单/报表等结构化数据文档。

> ⚠️ 安全提示(仅处理可信 PDF)
> 1. pdfplumber / pypdf / pymupdf 均需解析 PDF 内部对象结构,历史上出现过解析类漏洞。仅用于处理来源可信的 PDF;来源不明的外部 PDF 建议先在隔离环境预处理。
> 2. 图表 VLM 理解需要你自配 PDF2DOCX_VLM_ENDPOINT。只填自有内网或可信服务端点,不要填来源不明的第三方地址(避免把文档内容外发给不受控服务)。凭据走环境变量,不要写进脚本或提交到仓库。

何时使用

  • 用户给出一份 PDF 并要求转成 Word / 可编辑文档。
  • 用户强调「保留细节」「保留页码/引用」「生产级」「可追溯到原页」。
  • 文档含复杂表格、图表、脚注、页眉页脚,普通复制粘贴会丢结构。
  • 用户后续会对该文档做检索、问答或质量核验(闭环评测)。
  • 用户需要对 PDF 做加解密、填表单、电子签章,或在单个 PDF 内做关键词检索(补充能力,见下文)。

准备(依赖)

在任意 Python 3.10+ 环境中安装依赖:

# 一键安装(core + optional + dev 分层见 requirements.txt):
pip install -r requirements.txt

# 或按需分装 —— core(主流程 + PDF 工具四件套):
pip install pdfplumber pypdf python-docx openpyxl Pillow pymupdf
# 扫描件 OCR 可选:
pip install pytesseract pdf2image   # 另需系统安装 tesseract 与 poppler
# 双路索引的向量召回可选(缺失则降级 BM25):
pip install sentence-transformers
# 电子签章的可选 PKI 数字签名:
pip install endesive

若 OCR 依赖缺失,扫描件走「图片提取 + 视觉理解」降级路径,不阻塞主流程。

运行环境(Windows / 中文文档必须)

先设 PYTHONUTF8=1 再跑任何脚本——脚本里大量中文日志/路径/正则,默认 GBK 解释器下
print 与 subprocess 编解码会报 UnicodeEncodeError,或把中文写进报告时出现乱码:

$env:PYTHONUTF8=1          # PowerShell(当前会话)
set PYTHONUTF8=1           # cmd
python scripts\convert_to_docx.py &lt;in.pdf&gt; &lt;out.docx&gt;

回归脚本(回归脚本 / 闭环回归脚本(未随本包发布))同样需要该环境变量,否则断言输出会乱码。
解释器:Python 3.10 及以上(与 frontmatter requires.python 一致)。

执行流程

Step 1:识别 PDF 类型

对每一页判定类型,整本取主导类型,逐页标注:

类型 判定依据 处理方式
原生文本 PDF page.extract_text() 有效字符数充足(>50/页) 直接结构化抽取文本与表格
扫描件 PDF 每页文本量极低,但存在整页位图 OCR 识别;OCR 不可用则整页渲染为图,交视觉理解
图文混排 PDF 既有文本又有图表/图片块 文本走抽取,图表/复杂表格走视觉理解

判定逻辑见 scripts/convert_to_docx.py 的 detect_pdf_type()。

Step 2:还原文档结构

完整保留以下原始结构,映射到 Word 对应对象:

  • 页码:每个 chunk 在 chunks.jsonl 中标注来源页 page 字段;正文默认不再注入 [P.X] 内联标记(做 1:1 忠实副本),页级追溯由 chunks.jsonl / verify.py 承担。
  • 标题层级:以编号结构为主识别 H1–H4(1、/第X章→H1;1.1→H2;1.1.1→H3;1.1.1.1→H4),字号/加粗仅辅助。兼容「平级字号 PDF」(正文与各级标题同字号、仅靠编号区分层级),标题同字号 + 加粗以保持导航大纲可用。
  • ⚠️ 仅凭"编号+中文"会把正文当标题:1.1 为规范公司行政后勤管理,保障食堂…特制定本制度。 这种编号开头的正文段落(编号式条款极常见)必须被否决。heading_level() 走 _looks_like_heading() 三条约束:长度 ≤40 字、不含句末标点(。;!?)、顿号/逗号 ≤1 个。真标题(1.1 总则、2.1 适用范围)不受影响。误判后果严重:正文被当标题会让 build_chunks 段落归属整体错位,检索召回直接失效。
  • 章节与段落:标题与其下属段落归为一体;空行用段落间距而非空段落。
  • 表格:pdfplumber.extract_tables() 抽取为 Word 表格;抽取前跳过表格 bbox 内的正文文字,避免与表格对象重复。跨页长表当前为逐页独立抽取、不自动合并(已知限制,详见 references/pipeline.md 第 3 节及其「续表人工/半自动处理」)。
  • 🚨 铁律(用户 2026-09-21 明确指令):源表格是合并单元格的,产出的 Word 与 Excel 都必须还原同样的合并结构,与源 PDF 一致。 pdfplumber 会把合并表头拆散、摊平,甚至切出碎片表(实测:发票页表头被拆成 2 个残表)——不能直接拿抽取结果出表。必须用词坐标 / 表格线重建合并网格:Word 用 w:gridSpan(横向)+ w:vMerge(纵向),Excel 用 merge_cells。表头与表内文字一律用源文原文(含源自带拼写错误,如 "Contry of origin"),不翻译、不改写、不擅自拆列改名。非表格的版面元素(信头、表内末行的产地行、表下备注行)同样按源位置还原,见 references/pipeline.md 的坐标定位法(extract_words 的 y/x 判定表内/表外)。
  • 图片与图表:提取为图片文件,配题注「图 N(来源:PDF 第 X 页)」;图表经视觉理解生成文字说明后入正文(理解方式见后文「图表智能理解」章节,支持 VLM 自动或 Agent 用 Read 理解);过滤 1px 装饰细线等装饰图,仅抽取内容图表(信笺头/logo 区域不计入内容图)。
  • 页眉 / 页脚:信笺头抽成 Word header。convert_to_docx.py 的 _build_header() 会自动从 PDF 页首检测 2×2(或 n×m)信笺头表格,按源 PDF 的列宽比例复刻为带实线边框的表格(Table Grid + 显式 w:tblBorders 全边框),逐格还原文字/字号/字体;logo 抽入左上格(与文字同行);若检测到密级勾选行(含 □/■)则置于表下;并将页边距设成与 PDF 正文一致(扫描全页取正文边界,避免标题页居中文字干扰)。不再把页眉当内联文本丢进正文,也不再做成「logo+文本堆叠」的 1×2 表。正文侧同步剥离:extract_structure() 逐页计算信笺头下边界 lh_bottom(页首小表 bbox 底部 + 紧贴其下的密级行),正文文字行与内容表均按 lh_bottom 过滤,确保信笺头只出现在 Word header、不重复进正文。页脚自动还原源 PDF 每页底部的真实页脚文字(法律声明/版权声明等),逐行写入 Word 页脚由 Word 每页重复,字体/字号/颜色对齐源 PDF 探测结果;不再只写 PAGE/NUMPAGES 页码域(避免丢弃页脚正文)。

Step 3:语义切片与索引

按语义结构 chunk 切分,写入 chunks.jsonl(每条一行):

  • 标题 + 所属段落 归为一个 chunk。
  • 表格 单独结构化为一个 chunk(Markdown 表格 + 字段说明)。
  • 图片 / 图表 生成摘要作为一个 chunk,附图片路径。
  • 长表格 按行列字段转为结构化文本。

> ⚠️ 产物边界:chunks.jsonl 只由 build_index.py 产出,主转换命令 convert_to_docx.py 不生成它。
> 也就是说「页级可追溯 / 闭环核验」需要额外跑一次 build_index.py;只跑转换则只有 &lt;output&gt;_report.json 与 .preview.md。

每条 chunk 携带 metadata:

{
  &quot;doc_id&quot;: &quot;report-2026&quot;,
  &quot;page&quot;: 12,
  &quot;section&quot;: &quot;第三章 方法&quot;,
  &quot;title&quot;: &quot;3.2 实验设计&quot;,
  &quot;table_no&quot;: null,
  &quot;image_desc&quot;: null,
  &quot;version&quot;: &quot;2026-07-16&quot;,
  &quot;context&quot;: &quot;该片段归属原文第三章方法,位于第 12 页,承接 3.1 研究问题。&quot;
}

context 字段补充该片段在原文中的归属位置与前后文,便于检索召回后定位。

Step 4:双路索引与 Agent 调度

构建并行的两套索引(scripts/build_index.py):

  • 向量索引:语义召回,处理同义/改写问题(sentence-transformers 可用时启用,否则降级为 BM25)。
  • 关键词索引:精确术语、编号、字段名召回(BM25 / 倒排)。

按问题类型分发(scripts/retrieve.py):

问题类型 路径 负责模块
简单事实(术语/定义/数值) 向量召回 + 关键词召回 检索片段
多章节对比/综合 先检索,再由 Agent 规划阅读路径,逐页精读 读取指定页
表格/图表问题 调用视觉工具解析对应页区域 抽取表格 / 看图表
需原文佐证 返回带页码引用(P.X)的片段 返回引用

各模块职责明确:检索片段、读取指定页、抽取表格、看图表、返回引用,互不越界。

融合方式:两路召回后用 RRF(Reciprocal Rank Fusion) 融合,无需统一量纲。向量索引缺失或与建库模型不一致时优雅降级为纯 BM25 单路,并在输出中明确标注实际使用的检索路(dual_rrf / bm25_only),不做"号称双路实则单路"的表述。

输出规范(生产级 Word)

生成的 .docx 必须满足:

  1. 使用命名样式(Heading / Normal / 题注 / 脚注),不直接堆砌内联格式,保证可编辑。
  2. 表格使用显式列宽,避免后续在 LibreOffice / Google Docs 漂移。
  3. 正文默认不注入 [P.X] 内联页码标记(保持 1:1 忠实副本);页级可追溯由 chunks.jsonl 的 page 字段与 verify.py 的 [P.X] 引用承担。
  4. 图表配题注,复杂图表附视觉理解生成的说明文字。
  5. 页眉页脚、脚注、章节层级与原 PDF 一致。
  6. 字体与颜色对齐源 PDF:先用 analyze_typography() 探测正文/信笺头/页脚/标题的真实字体名、字号、颜色(含黑色即 None),再映射到 Word 样式;禁止写死「宋体 11」「黑体」等导致与源不符。CJK 文本必须设置 w:rFonts 的 w:eastAsia。
    - ⚠️ 颜色为 None(即源 PDF 黑色)必须显式写 RGBColor(0,0,0),绝不允许留空依赖样式继承:WPS 及部分 Word 主题会把「无显式颜色」的继承色渲染成蓝色,导致整篇黑字变蓝。落实三处:① set_run_font 中 rgb is None 时兜底为黑;② Normal/Heading 样式即便源色为 None 也显式设黑;③ add_heading/add_paragraph 不要用 add_heading(text) 直接塞文本,改为 add_heading(&#x27;&#x27;, level) 后 r = h.add_run(text) 再 set_run_font(r, ..., &#x27;None&#x27;, bold=True) 上色,避免 run 继承变蓝。
    - 每个文字按其源 PDF 实际颜色上色(黑→黑、红→红、其他→其他):抽结构时为每个 block 生成 runs(按词颜色分段,异色词断开,同色词合并,_word_color() 取词覆盖字符的颜色众数),build_docx 对每段 seg 用其 seg_color 调 set_run_font 上色;绝不用 body 字体探测的众数色统一覆盖所有文字。这样源 PDF 里的红色批注/强调、蓝色链接、绿色标注等都能原色还原,不被染黑。
    - ⚠️ 取色必须回退 non_stroking_color:pdfplumber 对非嵌入式色彩空间的 PDF 不填 char[&#x27;color&#x27;](值为 None),真实颜色在 char[&#x27;non_stroking_color&#x27;]。若只看 color,这类 PDF 的红字/蓝字会全部被当"黑色"写死 000000。统一走 char_color(ch):color 缺失即回退 non_stroking_color;color_repr() 另支持灰度标量与 CMYK 四分量。验证手法:造一份红字 PDF,检查输出 docx 的 run 色是否为红色(实测应为 CC0000 一类)而非 000000。
  7. 表格视觉规范(中文制度文档标准排版):
    - 单元格文字:水平居中 + 垂直居中(WD_ALIGN_PARAGRAPH.CENTER + WD_ALIGN_VERTICAL.CENTER)。
    - 表格内字号比正文小 1–1.5pt(推荐 9pt vs 正文 10.5pt,匹配 PDF 紧凑感)。
    - 表头行:加粗 + 浅灰底色(如 #F2F2F2)区分于数据行;用 _set_cell_shading(cell, &#x27;F2F2F2&#x27;) 实现。
    - 纵向合并后合并单元格同样设垂直居中。

输出规范(生产级 Excel,v1.0.3+)

对于发票/装箱单/报表等结构化数据文档,支持输出 Excel (.xlsx) 替代或补充 Word。

何时用 Excel 输出

  • 文档核心内容是表格数据(明细、数量、金额、规格等),需要后续计算/筛选/透视。
  • 需要真数值单元格(非文本),支持 SUM 公式、排序、筛选。
  • 需要公式闭环(合计行 = SUM(数据区)),可交叉验证。

Excel 输出规范

🚨 图表还原铁律(用户 2026-10-02 强化指令):源 PDF 里出现图表,转出的 Excel 必须包含对应的原生可编辑图表,不能只留数据表或静态截图。 凡 PDF 图表背后是表格数据(柱/条/折线/饼/散点等),都要用 openpyxl 的 BarChart / LineChart / PieChart 等重建为原生图表对象(配方见下方「原生可编辑图表 · Excel 侧」);低清/截断图按已核验表格数据重建。静态截图仅作兜底、不算达标。校验:重开 xlsx 确认 _charts 非空且系列名/数据引用正确(防漏挂或只贴图)。

  1. 🚨 合并结构与源一致(用户铁律,2026-09-21):源表格里横向/纵向合并的单元格,Excel 必须用 merge_cells 还原同样的合并区(实测样例:Marks 块 A5:B7、CIF 横跨 G5:H5、C/No 纵向合并 A8:A15、双层表头 A41:A42/B41:F41)。表头用源文原文。校验:重开文件核对 merged_cells.ranges 数量与坐标。
  2. 真数值单元格:数量/金额/单价等用 int/float 写入,不用文本;配 number_format 控制显示格式(如 #,##0 / 0.00 / 0.00000)。
  3. SUM 公式闭环:合计行用 =SUM(range) 而非硬编码数值,可在 Excel 中实时重算验证。
  4. 表格边框:显式 Border(left,right,top,bottom) 每格设置,不用默认无边框。
  5. 表头区分:加粗 + 浅灰底色(PatternFill);合计行加粗 + 浅黄底色。
  6. 图片嵌入不变形:add_image() 只设 img.width,img.height 按原始像素比例自动计算(用 PIL 读原始尺寸),绝不同设宽高强制拉伸。
  7. 多页合并为单 sheet:用灰色分隔条行(PAGE N)隔开不同页面区域,比多 sheet 更适合打印/审阅。
  8. 页脚页码:oddFooter.center.text = &#x27;&amp;P / &amp;N pages&#x27;。
  9. 非表格内容不丢:标题/买方信息/地址/签名/Insurance 声明等,作为文本行或嵌入图片放在表格区域上方/下方。

Excel 校验规范

  • 算术预检:构建前用 Decimal 精确校验每行 qty × price = amount,合计 = Σ明细,不过就中止。
  • 逐格校验:重新打开 xlsx,逐格比对数据/标签/公式,检查表头、表体、合计行、空单元格、合并格。
  • PDF 数字多重集比对:把 PDF 全文提取的所有数字 token 与 Excel 所有单元格数字做多重集比对,业务关键数字零缺失。

评测与反查核验(闭环)

最终交付前执行 scripts/verify.py,覆盖:

  • 答案正确性:关键事实是否来自原文 chunk。
  • 检索命中率:Top-K 是否包含相关 chunk。
  • 页码准确性:引用 [P.X] 是否落在真实页。
  • 表格解析准确度:表格行列无错位、无漏格。
  • OCR 无漏写:扫描件逐页比对,无整段缺失。
  • 图表理解准确度:图表摘要与视觉内容一致。

核验输出 verify_report.json,列出每条引用的页码、命中 chunk 与实际检索路(dual_rrf 双路融合 / bm25_only 降级单路),支持可追溯与闭环回归。

> 前置条件:verify.py 依赖 build_index.py 先产出 index_dir(含 chunks.jsonl / index.json,向量库可选)。未建索引直接跑 verify 会缺文件报错。

转换效果预览(无需 Word 也能看「长啥样」)

转换脚本结束时会额外生成 &lt;output&gt;.preview.md:把 Word 的页眉、标题层级、正文与所有表格
以 Markdown 镜像出来。打开它即可在不启动 Word 的情况下核对结构、层级与表格是否正确,
避免「只给命令不给效果图」的盲区。交付时 Agent 也会直接预览生成的 .docx 本身。

运行诊断与错误报告(不再静默跳过)

早期版本对图表/图片/扫描页的异常用 except: pass 直接吞掉,图片多的文档会「无声失败」、
图表没出来也查不到原因。现已改为:

  • 所有异常进入运行报告,并在控制台打印 [警告] / [错误](含页码、图序号、原因);
  • 末尾打印汇总:页数 / 表格(成功,失败) / 图表(成功,失败) / 扫描页 / OCR 可用否 / 警告与错误条数;
  • 同时写出 &lt;output&gt;_report.json(含 tables / table_fail / figures / figure_fail / scans / ocr_available / warnings / errors)。

排查清单:图表没出来 → 看 report 里 figure_fail 与 errors;表格错位 → 看 table_fail;
扫描件无文字 → 看 ocr_available(需装 pytesseract + tesseract)。

图表智能理解(文字说明)

PDF 里的图表/图片会被抽取为图片并写入 figures/,同时生成 figures_manifest.jsonl
(每条含 page / idx / path / width / height / caption)。文字说明有两种注入方式:

  1. 自动(配 VLM):设置环境变量 PDF2DOCX_VLM_ENDPOINT(服务需鉴权时,凭据同样以环境变量传入,变量名见 scripts/convert_to_docx.py 的环境变量读取处),
    脚本自动调用并写出 figures_desc.jsonl,生成 Word 时把说明追加进题注
    「图 N-M(来源:PDF 第 N 页):<说明>」。
  2. Agent 理解(无 VLM):Agent 用 Read 工具逐一查看 figures/fig_*.png,
    把说明写成 desc.jsonl(每行 {&quot;page&quot;:N,&quot;idx&quot;:M,&quot;desc&quot;:&quot;...&quot;}),再运行下方第 5 条命令写回。

该注入脚本按题注匹配、幂等追加说明,无需重跑整条流水线。

原生可编辑图表(Word/Excel,v1.2.0 XML 注入 / v1.3.0 COM 替换)

把结构化数据变成原生可编辑图表(非贴图):Word 里双击可改数据,Excel 里改引用即变。
典型场景:表格转出后补趋势图/对比图;PDF 中低清/截断图表按已核验表格数据重建。

Word 路线选择(先选路,再动手)

路线一:XML 注入(v1.2.0) 路线二:COM 替换(v1.3.0)
脚本 native_charts.py word_com_charts.py
前置环境 无 Word 也能跑(跨平台) 仅 Windows + 本机装有 Word(pywin32)
使用方式 文档中预先埋占位段落,从零注入 把已存在的图片(如转换产出的截图)锚点定位后原地替换
支持类型 簇状柱 / 折线(手写 XML 可扩展) 全部 XlChartType(柱/条/折线/饼…)
典型场景 生成期注入:正文预埋 [[CHART_1]] token 事后替换:PDF 原有图表的截图换成真图

Word 路线一:XML 注入(scripts/native_charts.py,手写 DrawingML)

⚠️ 本机 python-docx 实为旧 docx v1.2.0 别名,无 docx.chart / add_chart API,必须在 zip 层手写 OOXML。

from native_charts import inject_charts
specs = [dict(
    token=&quot;[[CHART_1]]&quot;,            # 文档中预先插入的占位段落文本(整段将被替换为居中图表)
    type=&quot;bar&quot;,                     # bar=簇状柱形 | line=折线(带标记)
    title=&quot;图表标题&quot;, cats=[&quot;2021届&quot;, &quot;2022届&quot;],
    series=[dict(name=&quot;大专&quot;, values=[6000, None], color=&quot;9E9E9E&quot;)],  # None=数据缺口
    width_cm=15.5, height_cm=8.5)]
inject_charts(&quot;out.docx&quot;, specs)    # 返回注入数

🚨 「渲染空白」三大根因(缺一必白屏,逐条自检):
1. word/charts/chartN.xml 与 word/embeddings/bookN.xlsx 必须作为 zip 成员真正写入(python-docx 的 relate_to 不会落盘);
2. [Content_Types].xml 必须注册 Override:chart=application/vnd.openxmlformats-officedocument.drawingml.chart+xml、嵌入簿=...spreadsheetml.sheet;
3. chart XML 须含 c:catAx/c:valAx(互指 c:axId)且写 strCache/numCache 缓存。

其他要点:
- 占位段落替换正则锚定到直接包含 token 的 &lt;w:p&gt;:r&quot;&lt;w:p\b[^&gt;]*&gt;(?:(?!&lt;/w:p&gt;).)*?TOKEN.*?&lt;/w:p&gt;&quot;,否则跨段落误吞正文;
- c:dispBlanksAs val=&quot;gap&quot; 让 None 呈现缺口;series numCache 中 None 直接省略 &lt;c:pt&gt;;
- 嵌入簿单元格闭合标签是 &lt;/c&gt; 不是 &lt;/c:r&gt;(属性 r 不是标签名——曾因此图表可渲染但 Word「编辑数据」打不开工作簿);
- wp:docPr id 用 900+ 避免与既有图片冲突;rId 取 document.xml.rels 现有最大值递增;
- 系列色对齐源图:c:spPr/a:solidFill/a:srgbClr。

Word 路线二:COM 替换(scripts/word_com_charts.py,v1.3.0+,需本机 Word)

把 docx 里已有的静态图(锚点定位)原地替换为原生可编辑图表,数据源是 xlsx 区域。
源自半导体行业人力报告实战(53 页 PDF → Word 16 张原生图一次收官 16/16)。

from word_com_charts import replace_images_with_charts
specs = [dict(
    name=&quot;涨薪率按城市&quot;,
    anchor={&quot;prev&quot;: &quot;图 3 主要城市涨薪率&quot;},   # 目标图前一非空块文本(包含匹配)
    chart_type=51,                            # 51 簇状柱 | 52 堆积柱 | 57 横条 | 65 折线 | -4120 饼
    title=&quot;主要城市涨薪率(%)&quot;, width_pt=400, height_pt=240,
    colors=[&quot;1F3864&quot;, &quot;ED7D31&quot;, &quot;C00000&quot;, &quot;70AD47&quot;, &quot;5B9BD5&quot;],
    legend=True,
    source=dict(cats=&quot;涨薪率!B19:G19&quot;,        # 类别区域(单行/单列,sheet 名必带)
                series=[{&quot;name&quot;: &quot;全国&quot;, &quot;ref&quot;: &quot;涨薪率!B20:G20&quot;},
                        {&quot;name_ref&quot;: &quot;涨薪率!C20&quot;, &quot;ref&quot;: &quot;涨薪率!C21:G21&quot;}]))]
report = replace_images_with_charts(&quot;out.docx&quot;, specs, xlsx_path=&quot;data.xlsx&quot;)
# report = {&quot;total&quot;, &quot;ok&quot;, &quot;failed&quot;, &quot;chart_parts&quot;};任一图失败自动回填原图并继续

CLI:python scripts/word_com_charts.py doc.docx --specs specs.json --xlsx data.xlsx --render-pdf 核对版.pdf

🚨 COM 路线四大坑(脚本已内建处理;本段与「常见陷阱」是唯一完整清单,改动前必读):

  1. AddChart2 默认仅 3 系列,扩列不自动跟随(实战最大根因):数据表 Resize 到 4-5 列后
    图表仍只绑前 3 列,取 SeriesCollection(4) 报 com_error"参数无效"(scode -2146827284)。
    必须在写完数据后显式重建系列:现有系列逐个改 Values/XValues 公式
    (sheet 名用 cws.Name 动态取并套单引号)+ NewSeries 补足 + 多余 Delete,
    最后断言 Count == nser;饼图(-4120)仅 1 系列豁免。全文档 N 张图只有 >3 系列的会炸,
    ≤3 系列全成功——这个"恰好吻合"模式就是此坑的指纹。
  2. 图表数据网格状态机:AddChart2 成功后 Word 弹出内嵌数据网格,未被"接管"
    (cd.Activate() + 写数据)前,下一次 AddChart2 报"网格已打开"/"参数无效"(同 scode)。
    铁律:插入后立即 Activate 写数据;Excel 进程全程不 Quit,保存后再统一退。
  3. zip 句柄泄漏 = Word 保存"文件许可权错误"真根因:Python 读 docx 的句柄不带
    FILE_SHARE_WRITE,全程阻塞 Word 写盘。zip 必须 with 即用即关。
  4. 导出核对版 PDF:ExportAsFixedFormat(path, 17)(17=wdExportFormatPDF,Excel 才是 0),
    路径必须反斜杠(正斜杠报"无法保存,只读文件")。

其他要点:

  • 锚点支持 {&quot;prev&quot;|&quot;next&quot;|&quot;prev_any&quot;|&quot;next_any&quot;: 文本}(包含匹配);替换按 ordinal 倒序
    保证定位稳定;目标必须是含 a:blip 的静态图(已是图表则拒绝替换,防重复运行误删);
  • Word 忙抛 CALL_REJECTED(-2147418111),脚本用重试包装(60 次 × 0.3s);
  • 异常退出残留三件套:~$xxx.docx 锁文件 + 隐形 WINWORD + 僵尸"Microsoft Word 中的图表 -
    Excel" OLE 实例——开工前脚本查锁文件;残留进程用
    tasklist //v | grep -iE &quot;winword|excel&quot;(看窗口标题)+ taskkill //F //PID 精清;
  • 验证方法论:矢量图表在导出 PDF 里没有 image 对象(pdfplumber 的 images 是页眉徽标),
    且大图会排到标注文字的前一页——用 fitz 渲染页面 PNG 亲眼目检,
    别拿 images/curves 计数下结论(详见「常见陷阱」末两条)。

Excel 侧:openpyxl 原生图表(非连续列逐列 Series)

非连续数据列(如大专/本科/硕士/博士在 B/C/F/I 列)逐列 Series(Reference(ws,col,r1,r2), title=&quot;名&quot;) 追加,再 chart.set_categories(Reference(...)) 统一挂类目;chart.y_axis.numFmt=&quot;#,##0&quot;;系列色 s.graphicalProperties.solidFill=&quot;RRGGBB&quot;(折线改 line.solidFill + s.marker 填色);折线必须 s.smooth=False。

闭环核验模式(实测 424 项中图表相关 12+ 项)

  • zip 级:chart/book 部件存在、CT Override 计数、document.xml 无 [[CHART 残留;
  • 结构级:chart XML 含 catAx/valAx/externalData;
  • 数值级(关键):提取 numCache 缓存值多重集 == 规范数据源对应列(防「图对了数错了」);
  • 嵌入簿可开:openpyxl 重开 bookN.xlsx 核对表头/数据(仅查图表缓存不够——见 changelog 1.2.0 的真 bug);
  • 兼容冒烟:python-docx 能重新打开注入后的 docx。

回归:# 原生图表注入回归(未随本包发布)(路线一)+ # COM 图表回归(未随本包发布)(路线二,无 Word 自动 SKIP),均 VERDICT 收尾。

补充能力(PDF 加解密 / 表单 / 签章 / 单文件检索)

除 PDF→Word/Excel 主流程外,本技能附带 4 个独立工具脚本,处理 PDF 本身的读写与安全操作。
以下用法均经实测验证(2026-09-18 冒烟回归)。

1. scripts/pdf_crypto.py — PDF 加解密(依赖 pypdf)

  • encrypt:加密 PDF。--user-pw 打开口令,--owner-pw 所有者口令(缺省同用户口令),--preset full|readonly 权限预设(readonly = 仅可打印 + 无障碍提取),--rc4 用 RC4 而非默认 AES-128。
  • decrypt:用 --password 去除加密。
  • info:查看是否加密。
  • 典型场景:对外发送敏感 PDF 前加密;回收带口令的 PDF 后解密归档。
python scripts/pdf_crypto.py encrypt input.pdf enc.pdf --user-pw 口令 [--owner-pw 权限口令] [--preset readonly]
python scripts/pdf_crypto.py decrypt enc.pdf dec.pdf --password 口令
python scripts/pdf_crypto.py info enc.pdf

2. scripts/pdf_form.py — 表单填写(依赖 pymupdf)

  • list:列出 PDF 内所有 AcroForm 字段(页/名称/类型/当前值)——必须先跑这步核对字段名。
  • fill:按 JSON 文件 批量写入(--data fields.json),字段名须与 PDF 中 field_name 完全一致;未匹配的字段名会 warn 列出。
  • 典型场景:批量填写固定格式申请表/审批单。
python scripts/pdf_form.py list input.pdf
echo &#x27;{&quot;name&quot;:&quot;张三&quot;,&quot;date&quot;:&quot;2026-09-18&quot;}&#x27; &gt; fields.json
python scripts/pdf_form.py fill input.pdf filled.pdf --data fields.json

3. scripts/pdf_sign.py — 电子签章(依赖 pymupdf,PKI 可选 endesive)

  • stamp:视觉签章——把签章图叠到指定页指定矩形坐标。坐标是必填:--x --y --w --h(PDF pt,1pt=1/72 inch,原点左下角),另有 --page(默认 1)、--rotate、--opacity(0~1)。
    ⚠️ 没有九宫格锚点(如 --pos bottom-right),必须自己算坐标。A4 为 595×842 pt。
  • sign:视觉签章 + 可选 PKI 数字签名(需 --cert/--key/--pin;未装 endesive 则仅完成视觉签章并提示)。
  • 典型场景:给已定稿 PDF 盖公章/签名图。
# A4 右下角盖 120x120pt 的章(留 100pt 边距)
python scripts/pdf_sign.py stamp input.pdf signed.pdf \
    --image seal.png --page 1 --x 375 --y 80 --w 120 --h 120 --opacity 0.9

4. scripts/pdf_search.py — 单文件 IR 检索(依赖 pdfplumber)

  • 免建索引检索:直接对单个 PDF 做 BM25 关键词检索,返回命中页与片段。支持 --topk(默认 5)、--chunk-lines(默认 3);query 传 .txt 则逐行作为多条查询。
  • 与主流程的区别:build_index.py/retrieve.py 面向多轮问答 + 双路召回 + 闭环核验(需建库);pdf_search.py 面向一次性快速查找(无需建库、无需 sentence-transformers,开箱即用)。
  • 典型场景:只想快速定位某份 PDF 里提到某关键词的页。
python scripts/pdf_search.py input.pdf &quot;关键词&quot; --topk 5

补充能力的安全与边界

  • 加解密口令不要写进脚本或提交到仓库;优先命令行交互或环境变量传入。
  • 电子签章:stamp 是视觉盖章(无密码学效力);需法律效力请走 sign 的 PKI 路径,并确保私钥保管安全。
  • 表单填写:先 list 看字段名再 fill,避免字段名不匹配静默失败。
  • 这 4 个脚本不改动源文件,一律输出新文件。

脚本用法

# 1) 端到端:PDF -&gt; 生产级 Word(顺带产出 _report.json 与 .preview.md)
python scripts/convert_to_docx.py input.pdf output.docx

# 2) 构建语义切片 + 双路索引(供检索/问答/核验)—— verify.py 的前置
python scripts/build_index.py input.pdf index_dir

# 3) 双路检索 + 路由(给定问题,返回带引用的 chunk)
python scripts/retrieve.py index_dir &quot;实验设计的样本量是多少?&quot;

# 4) 闭环反查核验(依赖第 2 步产出的 index_dir)
python scripts/verify.py index_dir questions.txt

# 5)(可选)把图表说明写回已生成的 Word(无 VLM 时由 Agent 用 Read 理解后调用)
python scripts/inject_figure_desc.py output.docx desc.jsonl

# 6) 补充能力:加解密 / 表单 / 签章 / 单文件检索(均为实测参数)
python scripts/pdf_crypto.py encrypt input.pdf enc.pdf --user-pw 口令
python scripts/pdf_crypto.py decrypt enc.pdf dec.pdf --password 口令
python scripts/pdf_form.py list input.pdf
python scripts/pdf_form.py fill input.pdf filled.pdf --data fields.json
python scripts/pdf_sign.py stamp input.pdf signed.pdf --image seal.png --page 1 --x 375 --y 80 --w 120 --h 120
python scripts/pdf_search.py input.pdf &quot;关键词&quot;

高效闭环(结构复用,避免二次解析)

转换与建索引本会对同一 PDF 各跑一遍 analyze_typography + extract_structure(2× 解析开销)。
若既要生产级 Word、又要页级追溯/闭环核验,用 --structure-out / --structure-in 让两步复用同一份结构:

python scripts/convert_to_docx.py input.pdf out.docx --structure-out structure.json
python scripts/build_index.py input.pdf index_dir --structure-in structure.json

convert_to_docx.py 把 {typography, structure} 落盘为 JSON;build_index.py 读到则跳过抽取直接切分建索引。
任一环节结构文件缺失/损坏会自动回退重新抽取,不影响产物。

转换还会额外产出:&lt;output&gt;_report.json(运行诊断)、&lt;output&gt;.preview.md(结构预览)、
&lt;output&gt;_images/figures/(抽取出的图表图片与 figures_manifest.jsonl 清单)。

非 PDF 源与快速 Markdown 转换(MarkItDown 通道)

本技能除 PDF 主流程(自有引擎)外,内置 MarkItDown 通道,用于把 非 PDF 源 或「只需快速转 Markdown」的需求转成 Markdown。

与自有引擎的分工

  • PDF → 生产级 Word/Excel(保细节 + 检索反查闭环):走 scripts/convert_to_docx.py 等自有引擎(见上文主流程)。需要像素级/结构级还原、页码可追溯时的唯一选择。
  • 非 PDF 源 / 快速 Markdown 提取:Word/PPT/Excel/图片(OCR)/音频/HTML/网页URL → Markdown,走 MarkItDown 通道。输出是 LLM 友好的线性 Markdown,不做像素级版式还原(无合并单元格、无精确坐标),适合检索/RAG/快速阅读,不适合当生产级可编辑文档。
  • PDF 两种都有:PDF 若只需快速抽文本/Markdown,也可直接用本通道(markitdown x.pdf -o x.md),不必跑完整生产级流水线;但要保细节/可追溯仍走自有引擎。

何时用 MarkItDown 通道

  • 源文件不是 PDF(Word/PPT/Excel/图片/音频/HTML)。
  • 用户只要「转成 Markdown / 提取纯文本」,不要生产级 Word。
  • 网页/URL、YouTube、ZIP 归档转文本。
  • 图片 OCR 提取、音频转写。

安装

pip install &#x27;markitdown[all]&#x27;        # 全格式
# 或按需:pip install &#x27;markitdown[pdf,docx,pptx,xlsx]&#x27;

命令速查

markitdown document.pdf -o output.md            # 文件转 Markdown
markitdown https://example.com/docs -o d.md     # 网页/URL
markitdown image.jpg -o o.md                    # 图片 OCR(需 Tesseract)
markitdown audio.mp3 -o t.md                    # 音频转写(需 audio-transcription 扩展)
# 批量(内置脚本)
python scripts/markitdown_batch_convert.py docs/*.pdf -o markdown/ -v

支持格式

格式 能力
Word (.docx) 标题/列表/表格/链接
PowerPoint (.pptx) 幻灯片文本/结构
Excel (.xlsx) 多表 → Markdown 表格
图片 OCR + EXIF(需 Tesseract)
音频 语音转写(需 audio-transcription 扩展)
HTML 结构保留
网页/URL、YouTube 抓取/转写
CSV/JSON/XML/ZIP/EPUB 可读 Markdown

Python API 速查

from markitdown import MarkItDown
md = MarkItDown()
print(md.convert(&quot;document.pdf&quot;).text_content)

OCR 前置依赖

# Windows:从 https://github.com/UB-Mannheim/tesseract/wiki 安装 Tesseract
# macOS:brew install tesseract

参考

  • references/markitdown_usage.md:详细示例(CLI / Python / 集成模式)
  • references/markitdown_reference.md:完整 API 参考与格式细节

相关技能

  • 本技能为自包含实现:scripts/ 引擎已封装文本/表格抽取(pdfplumber)、OCR(可选 pytesseract)、Word 生成(python-docx)、PDF 加解密/表单/签章/检索(pymupdf)等能力,无需安装其他技能。
  • 多模态图表理解依赖运行环境的视觉读取能力(Read 工具查看渲染后的图表图片)。
  • 与 已删除的图表技能 的关系(v1.2.0 更新):该技能已从本机删除,其核心的手写 DrawingML 原生图表注入能力自 v1.2.0 起并入本技能(scripts/native_charts.py,见「原生可编辑图表注入」章节)。需要图表在 Word/Excel 中为「原生可编辑对象」时直接用本技能,不再依赖外部技能。

常见陷阱

  • 🚨 合并表被 extract_tables() 摊平/拆碎(用户铁律场景,2026-09-21) → pdfplumber 对含合并单元格的表(发票/装箱单类)会把合并表头拆散甚至切出多个碎片表。源合并 → 产物合并:Word 用 w:gridSpan/w:vMerge 重建,Excel 用 merge_cells 重建。重建后必须校验:
  • Word:直解析 OOXML,对每个 &lt;w:tr&gt; 按其中 &lt;w:tc&gt; 出现顺序累加 gridSpan(无则计 1),总和 = tblGrid 的 gridCol 数。⚠️ python-docx 的 cell(ri,ci)/row.cells 在含 gridSpan 的行会按逻辑列重映射读错单元格,不能用它做网格校验。
  • Excel:重开核对 merged_cells.ranges(数量+坐标),非锚点 MergedCell 的 .value 只读(只能写锚点),但 border/alignment 可对区域内每格循环赋值。
  • 跨页长表被 extract_tables() 切成多块 → 当前脚本不自动合并(已知限制)。需要时按 references/pipeline.md 第 3.1 节人工/半自动处理:表头一致且中间无正文才合并,否则保持独立表格。统一抽取易产生幻影列/空行,关键文档建议用「已核验的干净表格数据」覆盖。
  • 扫描件 OCR 把图表当文字 → 图表区域单独走视觉理解,不进 OCR 文本。
  • 标题层级误判(平级字号 PDF) → 正文与标题同字号时,靠编号结构识别;勿仅靠字号阈值,否则 H1 计数可能为 0。
  • [P.X] 引用与实际页偏移 → 抽取与生成使用同一分页基准(pdfplumber 页码)。正文已默认不注入 [P.X] 内联标记(忠实副本),追溯走 chunks.jsonl/verify.py;若需正文内联标记(v1.4.0 已删除从未被调用的 _add_page_ref),在 build_docx() 段落分支自行追加小字号灰色 run 即可。
  • 只跑转换就想做闭环核验 → chunks.jsonl 只由 build_index.py 产出,必须先建索引再 verify.py,否则缺文件。
  • 表格列宽用百分比导致 Google Docs 漂移 → 用显式厘米宽度。
  • 字体写死导致与源不符 → 先 analyze_typography() 探测真实字体/颜色,再映射样式。
  • 正文/标题变蓝字 → 源 PDF 黑色文字探测为 None,若 set_run_font/样式不显式写 RGBColor(0,0,0),或 add_heading(text)/add_paragraph(text) 直接塞文本使 run 继承空色,WPS / 部分 Word 主题会把继承色渲染成蓝色。应对:① set_run_font 中 rgb is None 兜底黑色;② Normal/Heading 样式即便源色为 None 也显式设黑;③ 标题用 add_heading(&#x27;&#x27;, level) 后手动 add_run + set_run_font 上色。
  • re 原始字符串 \u 不转义 → 判断 CJK 用显式区间 &#x27;\u4e00&#x27; &lt;= ch &lt;= &#x27;\u9fff&#x27;,勿用 r&#x27;[一-鿿]&#x27;。
  • 取行字号用 line.startswith(c.text) → 多字符行永远取不到,应逐词重组行后按组内字符求字号。
  • 混合横竖版 PDF 必崩 → _build_header() 跨全部页算页边距,横版页 x1 超过竖版页宽度 → 负值右边距 → Cm(负数) 抛 ValueError。修复(v1.0.2):按同方向页组分别计算边距 + 负值钳位 0.5cm;build_docx() 检测方向变化时自动插入分节符(WD_SECTION_START.NEW_PAGE)+ 设置页面尺寸/方向 + 复制页眉页脚到新节。
  • ✅ 分节切回已修复(v1.1.2):原实现只在「方向 ≠ 首页方向」时开新节,导致 portrait→landscape→portrait 末尾段被锁在 landscape 节里。现改为跟踪「上一节方向」,凡与上一节方向不同(含横版切回竖版)都开新节并设正确尺寸/方向。闭环回归脚本(未随本包发布) 的 [6] 已固化 3 页 P/L/P 分节回归。
  • Excel 图片变形 → openpyxl add_image() 同时设 img.width 和 img.height 会强制拉伸。正确做法:用 PIL 读取原始像素尺寸,只设 img.width,img.height = int(width * orig_h / orig_w) 按比例自动计算。
  • Word 图片(澄清,非 bug) → convert_to_docx.py 用 add_picture(path, width=Cm(14)):只设宽度、不传高度,python-docx 会按源纵横比自动算高度,不会变形。代价是所有图统一 14cm 宽——源图小于 14cm 会被放大、源图极宽会较高。若需"只缩不放/按源像素限宽",改 _add_picture_fit() 即可,但默认行为已保比例。
  • 页眉 logo 被丢弃 → 黑字无标识 → 通用脚本已内置 extract_logo()(取首页 >20×20 图片裁剪为 logo.png)并嵌入 _build_header() 左上格,且有 if logo_path: 容错(提取失败跳过而非报错)。不要退化成「只放信笺头文字、丢 logo」的页眉;从本 skill 派生的定制脚本务必复刻此逻辑。
  • 信笺头重复进正文(v1.0.2 前的老 bug,已修) → 根因有二:① 正文文字行跳过阈值 top &lt; h*0.10 与页眉检测区域 h*0.15 不一致,信笺头表下半部(约 11% 处的「文件名称/版本」行)漏进正文;② page.extract_tables() 从不过滤信笺头表,致其每页作为内容表重复进正文。修复:逐页计算 lh_bottom(页首小表 bbox 底部,含 y1<h*0.30 防误判大表 + 紧贴其下 □/■ 密级行),文字行与内容表均按其过滤。派生脚本若复刻本逻辑,切勿再退回固定 0.10 阈值。

  • 🚨 页首 10% 被当成信笺头盲区 → 正文首段整段静默消失(v1.1.7 修复) → 旧版在未检测到信笺头表时仍默认 lh_bottom = h*0.10,凡 top 落在页首 10% 的正文行一律按信笺头丢弃。页边距 2cm(≈6.7% 页高)的常规文档,紧随页首标题之后的第一个正文段落必然落在该带内 —— 实测「1.1 为规范公司行政后勤管理,保障食堂…特制定本制度。」整段消失,chunks 里没有它、检索也召回不到。修法:只有在确实检测到信笺头表时才有排除下边界;无信笺头表时按「文字信笺头行」精确匹配剥离,不做位置盲删。

  • 🚨 内容表被误判为信笺头表(v1.1.7 修复) → 旧版 _build_header 只用「表格 top < 页高 15%」判定信笺头,extract_structure 却用「top<15% 且 bottom<30%」,两处阈值不一致;且都没限制表的大小。正文首屏的内容大表(4×6 装箱单等)会被误判:既被搬进 Word 页眉、又在正文里被过滤掉(内容静默消失且在每页页眉重复)。修法:新增共享 _detect_letterhead_table(),统一判据并追加「行数 ≤4 且列数 ≤4」的大小约束。
  • 🚨 合并单元格表导致 _build_header 抛 IndexError,整篇转换失败(v1.1.7 修复) → 旧版列宽只取首行单元格的右边界:首行含横向合并时边界被去重少算,col_w 长度 < n_cols → col_edges[i+1] 越界崩溃。实测页首 4×6 装箱单表转换直接失败。修法:列边界改取全表所有单元格 x0/x1 的并集,并按坐标定位列号、按跨度还原横向合并(cell.merge),不再用 enumerate 的序号当列号。
  • 🚨 文档标题被搬进 Word 页眉(v1.1.7 修复) → 旧版 extract_letterhead() 只按位置取行(top &lt; 页高 10%),会把页首的文档标题也当成信笺头:标题被写进页眉、正文里再也找不到它、且每页页眉重复。修法:新增 _letterhead_text_lines(),只取页首连续短行并在遇到标题/长句/句末标点时截断;并要求该行在后续页复现才判定为信笺头(单页文档无法核验 → 保守留在正文)。既无信笺头也无 logo 时页眉留空,不再回填正文、也不放「(信笺头)」占位符。
  • 🚨 单级编号的正文条款被误判为 H1(v1.1.7 修复) → v1.1.1 给多级编号分支加了 _looks_like_heading() 约束,单级分支(1、 / 1.)漏加,于是「5. 备注:本条款自发布之日起施行…。」「1、为规范公司…,特制定本制度。」这类正文条款被判成 H1,段落归属整体错位、检索失效。修法:单级分支同样过一遍标题性约束。
  • 🚨 COM 原生图替换:4-5 系列报"参数无效"(v1.3.0 实战最大坑) → AddChart2 默认图表只带 3 个系列,ListObject 扩列不会让图表跟随扩展(取 SeriesCollection(4) 即炸);全文档表现为"恰好只有 >3 系列的图失败、≤3 系列全成功"——这个模式就是此坑指纹。修法:写完数据后显式重建系列(改 Values/XValues 公式 + NewSeries 补足 + 断言 Count==nser),见「原生可编辑图表」路线二;COM 图表回归脚本(未随本包发布) 已固化 5/4 系列回归。
  • 🚨 COM 路线第二张 AddChart2 报"网格已打开" → 图表数据网格状态机:插入成功后 Word 弹内嵌数据网格,未被接管(cd.Activate() + 写数)前下一次插入必炸(同一 scode,极易误诊为"插入失败")。铁律:插入后立即 Activate 写数据;Excel 进程全程不 Quit,保存后再统一退。
  • Word 保存报"文件许可权错误" → 八成是 Python 侧 zip/docx 句柄未关(无 FILE_SHARE_WRITE,全程阻塞 Word 写盘)。zip 必须 with 即用即关;另查异常退出残留三件套:~$xxx.docx 锁文件 + 隐形 WINWORD + 僵尸"Microsoft Word 中的图表 - Excel" OLE 实例,tasklist //v 看窗口标题后 taskkill //F //PID 精清。
  • Word 的 ExportAsFixedFormat 报错 → ExportFormat 用 17(wdExportFormatPDF;Excel 的同名方法才是 0);路径必须反斜杠(正斜杠报"只读文件");dynamic dispatch 偶发 AttributeError 时用 EnsureDispatch 或重试。
  • 验证图表是否渲染成功,别拿 pdfplumber 的 images/curves 计数 → 矢量图表在导出 PDF 里没有 image 对象(images=1 是页眉徽标),且 400pt 大图在窄页上会排到标注文字的前一页(按标注文本定位页码会查错页)。正确姿势:fitz 渲染页面 PNG 亲眼目检;extract_text 出现轴刻度/标题文字是"图表在渲染"的关键线索。

Resources

scripts/(转换主流程)

  • convert_to_docx.py:端到端转换引擎(类型识别 → 结构还原 → Word 生成),含运行报告、Markdown 预览与图表清单;支持混合横竖版 PDF 自动分节;v1.4.0 起同一 PDF 单次打开解析(解析复用见 references/pipeline.md §2.6)。
  • inject_figure_desc.py:把图表智能理解的说明按题注写回已生成的 Word(幂等,无需重跑流水线)。
  • native_charts.py:原生可编辑图表注入引擎(Word 手写 DrawingML + 嵌入数据工作簿;Excel 配方见「原生可编辑图表」章节)。
  • word_com_charts.py:Word COM 原生图表替换引擎(v1.3.0+)——锚点定位已有静态图原地换成原生可编辑图,全 XlChartType,4-5+ 系列自动重建;需 Windows + 本机 Word。
  • build_index.py:语义切片 + 双路索引构建。
  • retrieve.py:双路检索与问题路由。
  • verify.py:闭环反查核验(双路 RRF 融合,向量缺失自动降级为 BM25 并标注)。

scripts/(PDF 工具,v1.1.0 并入)

  • pdf_crypto.py:PDF 加解密与权限设置。
  • pdf_form.py:AcroForm 表单读取与填写。
  • pdf_sign.py:视觉签章 + 可选 PKI 数字签章。
  • pdf_search.py:单 PDF 关键词检索(免建索引)。

Excel 输出(无独立脚本,方法论内置)

PDF→Excel 转换复用本技能的「已核验干净数据覆盖」原则:先用 pdfplumber 提取并逐格核验表格数据,再用 openpyxl 构建真数值单元格 + SUM 公式 + 图片嵌入(PIL 保宽高比)的单 sheet Excel。详见上方「生产级 Excel 输出规范」章节。

references/

  • pipeline.md:流程细节、启发式阈值与字段说明(按需加载)。

回归基线(scripts/回归脚本 + 闭环回归脚本(未随本包发布),非交付件,禁止清理)

合并 v1.1.0 时建立的回归测试,改脚本后应重跑以确认链路未破:

  • 主链路回归脚本(未随本包发布):造一份含信笺头+标题+表格+页脚的小 PDF,跑通
    convert_to_docx → build_index → retrieve → verify 全链路,断言四步 rc=0、
    六项产物存在、verify_report.json 内容合法。
  • 工具回归脚本(未随本包发布):对 4 个工具脚本(crypto/form/sign/search)逐条跑 CLI 并断言产出文件。
  • 闭环回归脚本(未随本包发布):内容级闭环核验(不只是"能不能跑",而是"产物对不对")。
    78 项断言覆盖字体/字号/颜色还原(含红字 CC0000)、信笺头与页脚文字、表格数值、
    检索 Top-1 命中含金额的表格 chunk、降级标记 bm25_only 等,以及 [7] 内容保真回归:
    页首正文段不得被静默丢弃、文档标题不得被搬进页眉、合并单元格表不得崩溃、
    单级编号正文句不得误判为标题、多页文字信笺头须进页眉且正文不重复。
    这是 v1.1.1 三个真实缺陷的唯一有效捕获手段,任何取色/切分/标题逻辑改动后必跑。

  • 原生图表回归脚本(未随本包发布):原生图表注入回归(v1.2.0)——占位替换、chart/book 部件落盘、
    CT 注册、轴结构、numCache 值断言、嵌入簿 openpyxl 重开、docx 可重开。
    首跑即捕获嵌入簿 &lt;/c:r&gt; 闭合标签真 bug。
    任何 native_charts.py 改动后必跑。

  • COM 图表回归脚本(未随本包发布):COM 替换路线回归(v1.3.0)——锚点未命中/锁文件两条负向路径、
    5 系列簇状柱 + 4 系列折线替换(>3 系列重建主坑)、c:ser 计数、numCache 值与源一致、
    嵌入簿 openpyxl 重开、docx 重开,共 19 项断言。
    无 pywin32 / 本机无 Word 时打印 SKIP 并以 0 退出。
    任何 word_com_charts.py 改动后必跑。

# 主链路回归(未随本包发布)        # 主链路回归
# 工具脚本 CLI 回归(未随本包发布)         # 4 个工具脚本回归
# 内容级闭环回归(未随本包发布)  # 内容级闭环(78 项)
# 原生图表注入回归(未随本包发布) # 原生图表注入回归(v1.2.0)
# COM 图表回归(未随本包发布) # COM 替换路线回归(v1.3.0,无 Word 自动 SKIP)
# 均以 VERDICT: PASS / FAIL 收尾,可直接用作 CI 断言

已知环境事实(2026-09-18 实测):本机 sentence-transformers 未安装,故
build_index.py 会明确报告 deps_missing 并降级为纯 BM25 单路;retrieve.py /
verify.py 的输出会标注 bm25_only。这不是故障,是预期降级。若要启用双路语义召回:

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple sentence-transformers
# 注意:首次使用需联网下载 paraphrase-multilingual-MiniLM-L12-v2(约 470MB)

若模型拉取失败,build_index.py 会报 model_unavailable 并给出 HF_HOME 提示,
不会静默伪装成"未启用"(这是 v1.1.0 修的行为,旧版会把三类失败吞成一种)。

常见问题

5 问
答案由本站依据条目字段整理
PDF大师:一键转Word/Excel怎么安装?

在支持 Skills 的客户端里执行:skillhub install user_99f4db18/pdf-to-detail-word。安装方式为未标注。装完刷新技能列表或重开客户端。

PDF大师:一键转Word/Excel支持哪些客户端?

资料没有标注宿主客户端,但只要客户端支持 Skills(Claude、Codex、Cursor 等),一般都能加载。

PDF大师:一键转Word/Excel权限高吗,安全吗?

权限级别为未标注权限。安装前先看它会读取或写入哪些内容。

PDF大师:一键转Word/Excel收费吗?

本站不代收费用,也没有标注具体价格。是否收费取决于技能本身和所用的模型或客户端,正式使用前按作者说明确认。

PDF大师:一键转Word/Excel用什么许可证?

许可证标注为 未说明(许可证不明确)。商用或二次分发前请到仓库确认条款原文。

热门专题

按场景挑技能
全部专题 →

技能内容以作者仓库为准;分类、权限级别与许可证状态的中文说明为中文整理,最近核验 2026-11-06。