# PDF Courseware To Obsidian

> 将本地 PDF/PPT 课件批量整理为图文并茂的 Obsidian 复习笔记知识库。当用户提供课件目录、想把讲义/课件/slides 转成结构化中文笔记、生成 Obsidian Vault、提取课件文本与配图时使用。触发词：整理课件、课件转笔记、PDF转笔记、Obsidian笔记、复习笔记、讲义整理、course notes。

- Skill: `phsecl/pdf-courseware-to-obsidian` (Agent Skill, multi-file: 7 files)
- Install (CLI): `npx skillmds@latest add phsecl/pdf-courseware-to-obsidian`
- Raw SKILL.md: https://api.skillmd.com/api/skills/phsecl/pdf-courseware-to-obsidian/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Docs & Writing
- Author: PhSeCl (https://skillmd.com/u/phsecl)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/phsecl/pdf-courseware-to-obsidian

---


# PDF 课件 → Obsidian 笔记知识库

你是一个全自动化的「学习助理」兼「数据处理工程师」。读取指定目录中的课件，去粗取精地重构，自动生成专为 **Obsidian** 优化、图文并茂的复习笔记知识库（Vault）。

> **解析引擎：MinerU（已彻底取代 markitdown / 本地 PyMuPDF 提取）。** MinerU(vlm 模型) 把 PPT 原生**矢量图**（数据通路图、流水线图、电路图、搜索树等）直接**渲染成清晰位图**，并把表格还原成 HTML、公式还原成 LaTeX、版面与标题层级一并还原——质量远高于旧方案，且**省掉了旧流程手动 `--render-pages` 截矢量图的环节**。

## 启动

确认理解后，向用户索要：
1. **源课件目录路径**（存放待整理课件）
2. **输出去向**——**每次整理前必问，不要替用户假设**（见下方「输出去向」）。
3. **MinerU Token**——调云端解析必需。让用户在 MinerU 控制台「API 管理」页创建，经 `--token` 传入或设环境变量 `MINERU_TOKEN`。**绝不把 Token 写进任何文件或提交到 git。** 若用户未给，停下来索要，不要猜。

### 输出去向（强制询问：现有仓库 or 新建仓库）

> [!important] 动手前必须用 AskUserQuestion 问清这一项——一个 Obsidian 仓库（Vault）只应有一份根 `.obsidian` 配置；若默认新建独立目录，多门课会散成多个仓库，事后还得手动合并。所以**每次都先问**用户把本次结果放到哪里：

**问题：本次笔记输出到哪里？** 两个选项——

- **A. 并入现有 Obsidian 仓库（推荐）**：让用户给出**现有仓库根路径**（如 `F:\ObsidianRepository`）。
  - 把本课程作为**该仓库下的一个子文件夹**输出：`<现有仓库根>/<课程名>/`（课程名默认取源目录名，可让用户改）。
  - 笔记 `*_笔记.md`、`00_课程总览_MOC.md`、`assets/`、临时 `_mineru/` 全部落在这个**子文件夹**内；脚本的 `--out` 指向子文件夹、`--assets` 指向 `<子文件夹>/assets`。
  - **不要**在子文件夹里建 `.obsidian`——它共用仓库根那一份配置。笔记里的图片引用一律相对路径 `./assets/...`，笔记与其 `assets` 同处子文件夹内即不断链。
  - **防撞名**：若 `<现有仓库根>/<课程名>/` 已存在，提示用户是沿用（增量补做）还是换名，别盲目覆盖。
- **B. 新建独立仓库**：在**源目录内**新建 `<源目录名>_Obsidian笔记`（如 `人工智能原理` → `人工智能原理_Obsidian笔记`）。
  - 这是一个独立 Vault，用户日后用 Obsidian「打开文件夹为仓库」单独打开。
  - **绝不**用固定通用名 `Obsidian_Course_Notes`——多门课会撞名、无法区分管理。中文名 Obsidian 完全支持，用户偏好英文也可用其指定名。

**幂等/防误建（两种去向都适用）**：动手前先检查目标输出目录（及历史/改名版本）是否已存在；**若已存在就沿用它**，绝不再新建同名/通用名空目录。后续重跑脚本，`--out` 必须指向这个**真实输出目录**。

> 下文统称该真实落盘目录为「输出目录」：去向 A 时它=`<现有仓库根>/<课程名>/`，去向 B 时它=`<源目录名>_Obsidian笔记/`。所有 `--out`、`--assets`、`./assets/` 引用、收尾清理均以此为准。

收齐源目录、输出去向、Token 后**静默启动整个流水线**，遇报错自主修复，全部落盘后再汇报总结。无需中间确认。

## 环境与工具链（不要重复造轮子）

- 用 `scoop` + `uv` 管理环境：缺 Python 用 `scoop install python`；规范使用 `uv init` / `uv add` / `uv run`。
- 安装依赖：`uv add requests PyMuPDF`（requests 调 API，PyMuPDF 拼接触表/读图尺寸）。
- 主脚本：**`scripts/mineru.py`**（MinerU 解析 + 选图三件套）。`scripts/extract.py` 仅作**无网络/API 失败时的离线兜底**，正常流程不用。

## 自动执行流水线

### 第一步：扫描与建库
- 列出源目录所有课件：`uv run python <skill>/scripts/mineru.py --list "源目录"`。
- **确认输出去向**：若启动时尚未问，先用 AskUserQuestion 问清「并入现有仓库 / 新建仓库」（见上「输出去向」），据此定出本次唯一的**输出目录**，并按命名规则确认/沿用、防撞名。

### 第二步：解析课件（MinerU 云端）

```bash
uv run python <skill>/scripts/mineru.py parse "课件.pdf" --out "输出目录" --token "$MINERU_TOKEN"
# 批量(≤50个，一次提交)：
uv run python <skill>/scripts/mineru.py parse "A.pdf" "B.pdf" --out "输出目录" --token "$MINERU_TOKEN"
```

> [!important] 大文件/慢任务的工具使用（务必遵守）
> - **云端解析较慢**（几十页到上百页可能数分钟至十几分钟）。`parse` 会**提交→轮询→下载→解压**全程阻塞，**请用 `run_in_background` 运行**，完成后你会被自动唤起，再继续读文本。不要用前台 `sleep` 干等。
> - **硬限制**：单文件 **≤200MB、≤200 页**；批量 ≤50 个。每账号每天 **1000 页**最高优先级额度，超出降速。
> - **超 200 页**：脚本会报错要求分段。用 `--page-ranges "1-200"`、再 `--page-ranges "201--1"` **分多次解析**，对应「超长课件分块处理」把各段追加进**同一个** `.md`。
> - 默认 `--model vlm`（图密集课件首选）。中文默认 `--language ch`。
> - 解析产物落在 `输出目录/_mineru/<课件名>/`（含 `images/`、`full.md`、`*content_list.json`），并自动生成 `_imgmap_<课件名>.txt` 与接触表（stderr 打印路径）。

### 第二步半：串行还是并发分发（多/大课件防溢出，动手前必判）

> [!important] 单课件闭环若**全在主进程串行**，多篇/大篇会让 `full.md` 正文 + 图像 Read（**视觉 token 最贵**）+ 重构全文在主窗口**线性累积**——处理到后面注意力稀释、幻觉严重。解法：把每个「单课件闭环」隔离进**独立上下文窗口**。

**分发决策：**
- **课件 ≤3 篇且均不算大** → 主进程**串行**逐个执行第三步（subagent 冷启动开销不值）。
- **课件 ≥4 篇，或存在单篇过大（>100 页 / `full.md` 一次读不完）** → **下发给 fresh 子 agent 并发**，**并发度 2–3**（图像处理重，过载得不偿失）。

**并发前必做——制定「大纲 contract」（统领进程的活）：** parse 完成后，主进程**只 Grep 各 `full.md` 的 `^#`/`^##` 标题大纲**（绝不读全文，否则正文又被吸进主窗口、隔离失效），据此定出全局蓝图、写成一份简短 contract：
- 全局**章节清单**：每个课件 → 最终笔记文件名 `<课件名>_笔记.md`；
- 每篇**一句话定位**（在课程中的地位、前后衔接）；
- 统一的**输出目录 / assets 路径**与双链命名约定。
> 这份 contract 是每个子 agent「知道自己是谁、兄弟章节叫什么」的唯一依据——**没有它，子 agent 各写各的，跨章节互链全成死链。**

**下发给每个子 agent 的 prompt 要点**（用 Agent 工具，`subagent_type=general-purpose`；**绝不用 fork**——fork 继承主上下文，等于没隔离）：
1. 「读 `<skill>/SKILL.md` 的**第三步单课件闭环 + 图片甄别准则 + Obsidian 格式规范**，对课件 `<课件名>` 执行单课件闭环。」
2. 附上：该课件 `_mineru/<课件名>/` 路径、输出目录、assets 路径、**大纲 contract 全文**。
3. 要求：full.md 读取、三级选图、图像 Read **全部在子 agent 自己窗口内完成**；落盘 `<课件名>_笔记.md`；**只回一行摘要**（文件名 / 嵌图数 / 异常或零图说明），**绝不回传笔记全文**。

**并发安全**：各子 agent 写同一个 `assets/`，但 collect 按 `<课件名>_pX_Y` 前缀重命名、不撞名；MinerU 已在第二步由主进程批量 parse 完，**子 agent 不调 API**、只读 `_mineru/` 产物——并发压力小。跨章节互链错误由第四步 `check_links.py` 统一兜底（这正是并发架构的安全网）。

### 第三步：逐个课件闭环（防上下文溢出）
**无论主进程串行、还是子 agent 并发，每个课件都执行下面这同一套闭环。** 对每一个课件：

1. **读取正文**：用 Read 读 `输出目录/_mineru/<课件名>/full.md`（**不要**用 cat/管道打印——Windows GBK 易乱码；脚本产物均 UTF-8）。
   - full.md 已按版面顺序把**图片插在对应正文处**（`![](images/xxx.jpg)`）、表格为 HTML、公式为 LaTeX——读它即可同时掌握「讲什么 + 图在哪段」。
   - **先判断大小**：stderr 已报告页数；也可 `wc -l`/`wc -c`。**过大（一次读不完）时按「超长课件分块处理」**，用 Read 的 `offset`/`limit` 分段，切勿截断或跳过内容。
2. **选图（强制步骤，不可跳过）**：按「**索引圈定 → 接触表扫览 → 放大核验**」三级漏斗，**逐级缩小、绝不一次性 Read 一大堆原图**：
   1. **索引圈定**：Read `_imgmap_<课件名>.txt`（一行一图：页码/友好键/文件/尺寸/**体积KB**/标记/caption）。结合 full.md 里图的上下文 + 每张图的 `<details><summary>类型</summary>` 标签（`natural_image`/`text_image` 多为装饰），圈出少量候选（每篇 5–10 个）。**标 `⚠碎片/装饰(体积过小)` 的默认排除**；标 `·近正方形` 的标为"需核验"。
   2. **接触表扫览**：Read `_contactsheet_<课件名>.png`，对候选做"示意图 vs 装饰图"视觉初筛。
   3. **放大核验**：对仍要嵌入或拿不准的候选，生成核验拼图、**Read 这一张**同时看清多张：
      ```bash
      uv run python <skill>/scripts/mineru.py inspect "p8_1,p33_1,p41_1" --doc "输出目录/_mineru/<课件名>"
      ```
   - ⛔ **批量读图硬规则**：直接 Read 原图时**单次最多 3 张**，任一图长边 > ~1500px 必须单独 Read（多图请求每张约 2000px 上限，超限整批被拒）。要一次比对多张就用 `inspect`。
   - **目标**：为每篇选出可嵌入的图。**凡最终要嵌入的图，必须已在 inspect 拼图或原图里被你真正看清。**
3. **拷图入库**：把选定的图拷进 Vault 的 `assets/` 并自动重命名：
   ```bash
   uv run python <skill>/scripts/mineru.py collect --doc "输出目录/_mineru/<课件名>" --pick "p5_1,p9_1,p105_1" --assets "输出目录/assets"
   ```
   命令会打印可直接写进笔记的引用（`![]( ./assets/<课件名>_p5_1.jpg )`）。
4. **重构润色 + 嵌图**：按下方「格式规范」去粗取精地重写；把选中的图按「图文并茂」插到对应讲解处，每张配一句中文图说（**图说必须如实描述图本身**）。
   - ⚠ **凡引用题目必附原题（强制）**：课件里的例题、习题、课堂练习、自测题——无论是用来讲解知识点的例题，还是章末练习——都**必须先完整抄录原题题面**（题干 + 全部已知条件 + 选项/图表/数据），再给解答/答案。**绝不允许「只给答案不给题」或「只描述大意」**，否则笔记脱离原题、无法复习。详见「格式规范」的「题目必带原题」条。
5. **直接落盘**：用 Write 把重构后的 Markdown 写入 `输出目录/<课件名>_笔记.md`。**绝不在聊天窗口输出笔记全文。**
6. **落盘自检（强制）**：用 Grep 数本篇 `!\[.*\]\(\./assets` 引用数。若为 **0**：回第 2 步补图，或——仅当确认该课件无任何可用示意图时——在日志注明「无可用图」。
   - ⚠ **引用≠已拷贝：逐张核验被引用的图真实存在**。写下 `![](./assets/X)` 不代表 `collect` 真把 X 拷进了 assets——只数引用条数会放过「写了引用却没拷图」的破图（实测某章漏 collect 一张图，图谱里成了死节点）。落盘后务必对**每个**被引用文件名 `Test-Path "<assets>/<文件名>"` 或 `ls assets/` 比对，确认无一缺失；缺了就重跑 `collect` 把它补进去（必要时从原 PDF 渲染该页裁图）。注意被引文件名含 `(1)` 等括号、图说含 `]`（如 LaTeX 区间 `[γx,γx+d-f]`）时，用「匹配到扩展名收尾」的正则提取路径，别用排除 `)`/`]` 的字符类（会截断漏检）。
   - **图说-实物一致性复核**：逐条核对每张嵌图是否被真正看清过、图说是否如实；带过 `·近正方形`/拿不准的图此刻必须已 Read 过原图，发现二维码/装饰图或图说不符立即删/换。
7. **进度汇报**：每完成一个输出一行，如：
   `✅ [1/8]《课件A.pdf》处理完成，嵌入 4 张图，已生成 课件A_笔记.md`

### 📌 图片甄别准则（决定「嵌哪些图」的核心规则）

1. **只嵌有信息量的图，丢弃装饰图与碎片。**
   - ✅ **该嵌**：数据通路图、流水线时空图/各阶段快照、状态/转移图、搜索树/博弈树/决策树、电路/逻辑门图、坐标曲线、网格世界、带数据的表格图、公式推导图。
   - ❌ **别嵌**：卡通吉祥物/剪贴画、纯照片、视频/IDE 截图、**二维码/签到码**、人像；**固定尺寸反复出现的小图**（六边形蜂窝、校徽拼贴、课程 logo）是**每页装饰模板**——inspect 一张即可批量排除（实测某课程 18 张 `201×201` 六边形装饰图全是模板）。
   - ❌ **碎片**：MinerU 偶尔把大图周边的**箭头、阶段标签**等切成独立小图。**`_imgmap` 里体积 `<4KB`（脚本已标 `⚠碎片/装饰`）的，默认一律不嵌**——实测红色装饰箭头、"ld/Write-back" 标签碎片都落在此区间。
   - 🔍 **善用 full.md 的类型标签（第一手选图信号）**：MinerU 在每张图下用 `<details><summary>类型</summary>` 标注图性质——`natural_image`=照片/装饰（基本别嵌）、`text_image`=文字截图（多别嵌）、`flowchart`=VLM 转的 mermaid（**别直接用**，仅提示"此处有图"，去 `_imgmap` 选对应渲染位图）、`line chart`/`bar chart`/`table`=**MinerU 已转成 markdown 表格，直接用文字表格、无需当图**、`interline_equation`=已转 LaTeX。
2. **图说必须基于图片真实内容**，写 `![图说](...)` 前要么已看清这张图画了什么，要么不嵌。严禁用相邻标题去套一张没真正看清的图。
3. **矢量图已由 MinerU 渲染好——不需要再手动截图。** 旧流程的 `--render-pages` 已废弃：数据通路/流水线/电路等 PPT 矢量图，MinerU 都已渲染成清晰位图存于 `images/`、并出现在 `_imgmap` 中，直接选用即可。实测 p70/p105/p140 等最复杂的流水线图渲染**清晰完整**。
4. **不要嵌入 MinerU 生成的 mermaid。** MinerU 的 `middle.json` 里有 VLM 把图转的 mermaid，但**实测复杂图幻觉严重**（连线乱编、节点刷屏式重复几十个），仅 ≤8 节点的极简示意图偶尔可用。**默认策略：一律使用渲染位图，不嵌 mermaid。**
5. **原图没有、或不适合的难点，主动用代码画图（学习者视角的关键，最易被忽略）。** MinerU 只给位图原图；很多**过程/对比/推导类**重难点并无现成好图，应主动用 **Markdown 表格 / 代码块 / ASCII / LaTeX** 画出来，胜过硬凑原图。实战验证极有效的几类：
   - **流水线时空图**（指令×周期网格，展示重叠执行 / 前递箭头 / 气泡停顿）——学流水线第一图，原图只有"快照"，**必须自己用表格画**。
   - **状态/数值对比表**（如 Cache 三种映射对同一访问序列的命中/缺失追踪、相联度对比）。
   - **算例竖式**（补码减法、物理地址计算、汉明码纠错）用代码块逐步展开。
   - **结构/布局图**（进程内存布局 栈↓堆↑、大小端字节排列、汉明码位布局表）用 ASCII / 表格。
   > **「图文并茂」= 渲染位图（讲结构）+ 自绘代码图（讲过程/对比/算例）**，两者缺一不可。落盘前自问：本章最难的概念，学习者能"看图"理解吗？
6. **二维码/签到图专项防范**：老师常在某页插微信签到二维码（该页正文往往很少）。凡 `_imgmap` 标 `·近正方形`、或在接触表里呈"近正方形点阵/色块"的图，**一律先 Read 原图核验**，确认是二维码/签到就丢弃。
7. **过程/算法/公式越重的章节越要配图**；每篇一般**嵌 2–5 张**精选位图 + 按需自绘代码图，**与讲解锚定**才有价值。

### 超长课件分块处理（防内容丢失）
当 `full.md` 过长、一次读取/重构会溢出上下文，或课件 >200 页需分段解析时：

1. **分段解析（仅 >200 页时）**：`--page-ranges "1-200"`、`--page-ranges "201--1"` 分多次 `parse`；各段产物在各自 `_mineru/<课件名>/`，注意区分。
2. **先规划切分点**：用 Grep `^## ` 列出 full.md 的标题大纲，按**逻辑小节**（而非死板页码）定切分点——这样每块内容连贯、不会从概念中间断开（实测处理 140+ 页大章很有效）。
3. **分段读取**：用 Read 的 `offset`+`limit` 按规划好的区间分批读 full.md（每次约 1000–1180 行，刚好在单次读取 ~25k token 上限内）。
4. **首块建文件**：第一块用 Write 创建 `<课件名>_笔记.md`，写 **YAML Frontmatter + 标题 + 导览 + 第一部分**，文件末尾留一行追加锚：
   ```
   <!-- APPEND-HERE -->
   ```
5. **后续块追加**：每段处理完，用 Edit 把锚替换为「**本段新内容 + 换行 + 同一个锚**」（`old_string` 用 `<!-- APPEND-HERE -->`），实现可靠追加不覆盖。
6. **收尾**：最后一块写完，用 Edit 把末尾锚替换为「本章小结 + 自测题」（移除锚）。
7. **校验**：`wc -l` 对比 .md 与 full.md，确认各页区间均已纳入；进度日志注明分块。

### 第四步：收尾（统一由主进程／统领进程执行）
> 并发模式下，先汇总各子 agent 回传的一行摘要，再跑下列全局关卡——`check_links.py` 正是兜底子 agent 各自为政造成的跨章节互链/破图错误的安全网。

1. **全局配图质检（强制关卡）**：对所有 `*_笔记.md` 用 Grep（`output_mode=count`，pattern `!\[.*\]\(\./assets`）统计每篇图片数。
   - **任何 0 图笔记**：除非确认其课件无可用示意图，否则回去补图。
   - **链接完整性校验（用脚本，别靠肉眼）**：运行 `uv run python <skill>/scripts/check_links.py "输出目录"`（整库可传仓库根）。它报告三类问题并以非零退出码标记：① **死链** `[[目标]]` 的 `.md` 不存在；② **失效锚点** `[[笔记#标题]]` 的标题不存在；③ **破图** `assets/` 图缺失（已正确处理含 `(1)` 括号的文件名）。**必须修到 0**：死链按「格式规范」的双链规则改为真实文件/锚点链或解链为纯文本，破图回去补图/改名。
   - **碎片/二维码复查**：回看引用了 `·近正方形` 图的笔记，Read 原图确认非二维码/装饰。
2. **Callout 表格渲染修复（强制，最易漏）**：callout 内表格缺前置空 `>` 行会渲染成原始管道符文本。落盘后用脚本批量补全：
   ```python
   import glob,re
   for md in glob.glob(r"输出目录/*.md"):
       lines=open(md,encoding='utf-8').read().split('\n'); out=[]
       for ln in lines:
           prev=out[-1] if out else ''
           if re.match(r'^>\s*\|',ln) and not re.match(r'^>\s*\|',prev) and not re.match(r'^>\s*$',prev):
               out.append('>')          # 表格首行前补空 callout 行
           out.append(ln)
       open(md,'w',encoding='utf-8').write('\n'.join(out))
   ```
3. **学习者视角审查（强制关卡）**：通读每篇，自问四件事——① 是否**真实浓缩**教学内容、无遗漏关键点？② **重难点**是否说清？③ **最难的概念有没有图**（渲染原图 or 自绘代码图）？典型缺口：流水线时空图、Cache 映射命中/缺失对比、补码/汉明码算例、内存布局——缺则按「图片甄别准则 5」用代码补画。④ **每道题是否都附了完整原题**？逐篇扫一遍所有例题/练习/自测题，发现「只给答案没给题」「只概括题意不抄题面」的，回去把原题题面（题干+条件+选项+题图）补全——见「格式规范」的「题目必带原题」条。
4. 生成总览索引 `00_课程总览_MOC.md`（学习路线图 + 章节表 + **章节笔记**双链）。MOC 里的双链一律指向真实章节 `.md`；"核心概念索引"用加粗或锚点链 `[[章节笔记#小节标题]]` 列出，**不要写 `[[裸概念名]]`**（否则 MOC 会批量制造死链——这是最常见的翻车点）。
5. **删除临时工作区**：整个 `输出目录/_mineru/`（含解析产物、`_imgmap_*.txt`、`_contactsheet_*.png`、`_inspect_*.png`）——仅供解析/选图，不入库。**已 collect 进 `assets/` 的图会保留**。
6. 汇报最终总结（章节数、图片总数、**已配图笔记数 / 总笔记数**、若有零图笔记说明原因、输出位置）。

## Obsidian 格式规范（写入 .md 的内容要求）

- **YAML Frontmatter**：`title`、`tags`、`source`、`date`，可加 `course`。
- **图片嵌入（重点，易漏）**：在核心概念/公式处精准插入 `![中文图说](./assets/对应图名.png)`，每张配一句要点。选哪些见「图片甄别准则」；每篇落盘后必做自检，确保非零图。
- **自绘代码图（强制考虑，非可选）**：见「图片甄别准则 5」。每章落盘前自问"最难的概念能看图理解吗"，对流水线时空图、状态对比、算例竖式、结构布局等用表格/代码块/ASCII/LaTeX 画出来。
- 📝 **题目必带原题（强制，最易偷懒）**：笔记里**任何**出现的题目——讲知识点用的例题、课堂练习、章末习题、自测题，无论来源——都必须**先完整给出原题题面，再给解答**。
  - **原题要素一个不漏**：题干文字、全部已知条件/数据、选项（选择题）、涉及的图/表/公式；课件里题目自带的图就按「图片甄别准则」把那张题图也嵌进来。题目较长就用 `> [!example] 例题` / `> [!question] 练习` callout 原样抄录，解答紧随其后（可用 `> [!success] 解答` 或折叠块）。
  - ⛔ **严禁三种偷懒写法**：① 只写答案/结论不写题（如直接给"答案：1 2 4 8 9 5 10 11"却不给题）；② 只用一句话概括题意而不抄题面（"一道关于 BFS 的题"）；③ 把题目细节删成"略"。**读者不翻原课件就应能独立看懂并重做这道题**——这是硬标准。
  - **自测题同理**：章末「自测题」每道也要是**可独立作答的完整题目**，而非泛泛的复习提示。
- ⚠️ **Callout 内的表格/代码块必须前置一个空 `>` 行**（Obsidian 硬规则，最易踩坑）：紧跟在文字行后的表格**不会渲染**、显示为原始管道符。正确写法：
  ```
  > [!note] 标题
  > 说明文字……
  >                ← 这一空 > 行不可省
  > | 列1 | 列2 |
  > |---|---|
  ```
  （callout **外**的普通表格无此要求。）收尾会用脚本统一校验修复。
- **排版增强**：
  - 逻辑清晰的多级标题（`#`）。
  - 大量使用 Callout：`> [!note]` `> [!important]` `> [!warning]` `> [!example]` `> [!summary]` `> [!question]` 等。
  - **双链（`[[...]]`）只指向真实存在的目标，否则即死链**——Obsidian 图谱里成空节点，误点还会在根目录生成空笔记。两种合法写法：① 章节互链 `[[其它章节笔记]]`（名字须与真实 `.md` 完全一致，注意别写错编号）；② 指向某章小节用锚点链 `[[章节笔记#小节标题]]`（`#` 后标题须与目标里的标题逐字一致）。
  - ⛔ **绝不给「概念名词」加裸双链**（如 `[[贝叶斯定理]]`、`[[欧拉角]]`、`[[指令系统]]`、`[[MCMC]]`）——它们通常没有对应 `.md`，是死链与图谱空节点的**头号来源**。概念名词一律用**加粗**或普通文本；仅当该概念**确有**独立笔记时才链它。
  - ⛔ **不为单个概念单开一篇 `.md`**：本类库按课件章节组织，概念应留在所属章节的小节里，需被引用时用 `[[章节笔记#小节标题]]`，而非新建概念页（实测既与章节内容重复、又是结构异类）。
  - 每章末尾可留「相关章节」行，仅链**真实存在**的兄弟章节笔记。
  - 每章末尾附「本章小结」+「自测题」。
- **公式**：LaTeX（`$...$` / `$$...$$`）。
- **语言**：全中文；核心术语首次出现附英文，如 数据通路（Datapath）。

## 脚本参数速查（scripts/mineru.py）

| 命令 | 作用 |
| --- | --- |
| `--list DIR` | 列出目录下所有可解析课件 |
| `parse FILES... --out DIR --token T` | 提交→轮询→下载→解压→生成选图三件套（**建议 run_in_background**） |
| `parse ... --model vlm\|pipeline` | 模型版本，默认 `vlm` |
| `parse ... --page-ranges "1-200"` | 页码范围；文件 >200 页时**必填**，分段多次解析 |
| `parse ... --language ch` | 文档语言，默认 ch |
| `parse ... --timeout 1800` | 轮询超时秒数 |
| `fetch BATCH_ID --out DIR --token T` | 凭 batch_id 断点续取（parse 超时后用） |
| `imgmap --doc DOC` | （重）生成图片索引 |
| `contact --doc DOC` | （重）生成接触表 |
| `inspect "p8_1,p33_1" --doc DOC` | 放大核验若干候选图，Read 一张同时核验多张 |
| `collect --doc DOC --pick "p5_1,p9_1" --assets DIR` | 把选中图拷入 assets 并重命名，打印可直接用的引用 |

> Token 经 `--token` 或环境变量 `MINERU_TOKEN` 传入，**脚本零硬编码**。`DOC` 指 `输出目录/_mineru/<课件名>`。
>
> **选图三件套（parse 后自动生成前两件）**：
> - **图片索引** `_imgmap_<课件名>.txt`：一行一图（页码/友好键/文件/尺寸/**体积KB**/标记/caption）。**先 Read 它**圈定候选；体积 `<4KB` 的碎片/装饰已自动标 `⚠`。
> - **接触表** `_contactsheet_<课件名>.png`：4 列缩略图总览，做视觉初筛。
> - **核验拼图** `_inspect_<课件名>.png`（按需 `inspect` 生成）：把一小撮候选放大拼到一张，**Read 一张同时核验多张**，避免批量 Read 原图触发尺寸上限。

## 迁移说明

本 skill 自包含、零硬编码：将整个 `pdf-courseware-to-obsidian/` 拷到任意项目的 `.claude/skills/` 或用户级 `~/.claude/skills/` 即可。脚本依赖 `requests` + `PyMuPDF`；Token 与所有路径/阈值均经命令行或环境变量传入。`scripts/extract.py`（PyMuPDF 本地提取）保留为无网络时的离线兜底；`scripts/check_links.py` 是收尾的链接完整性校验器（死链 / 失效锚点 / 破图），零依赖、可对任意 Obsidian 库单独运行。

