PDF 解析

SkillDocs & knowledge

Choose between docling, liteparse and pdfplumber for PDF extraction — tables, layout, fonts, screenshots, vector graphics.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the PDF 解析 skill

What this skill tells your AI

The instructions your AI receives, as published by jokull/icelandic-data in .agents/skills/pdf-parsing/SKILL.md and read by ahel’s review.

目标

把 PDF 文档解析成本地可读取、可搜索、可复制的 Markdown,并抽取 PDF 中的图片资源。解析完成后,后续阅读应优先使用本地 Markdown 文件;重复调用 structai.read_pdf 也会优先复用本地解析结果,不会在本地结果已存在时重复上传同一个 PDF。

依赖安装

当前 skill 对照的关键解析依赖:

  • structai package version:0.1.24
  • structai GitHub HEAD:d20df602578bee124a9c93b293493e63212d0aab
  • 更新本 skill 前,先确认 structai.read_pdf 行为是否变化;如果上游版本或 HEAD 变化,必须重新阅读 read_pdf 源码和 structai_skill() 输出。
pip install structai

如果包索引中找不到 structai,或需要使用 GitHub 仓库中的最新代码:

pip install "git+https://github.com/black-yt/structai.git"

校验:

python3 -c "from structai import read_pdf; import inspect; print(inspect.signature(read_pdf))"

如果当前环境同时有多个 Python,请确认 pippython3 指向同一个环境:

python3 -m pip show structai
python3 -c "import structai; print(structai.__file__)"

read_pdf 源码追溯

  • read_pdf 行为以当前安装版本源码为准;如果缓存、上传、下载、图片路径或返回值和预期不一致,先读源码再判断。
  • inspect.signature(read_pdf) 用于看函数参数。
  • inspect.getsource(read_pdf) 用于看 read_pdf 入口逻辑。
  • structai.__file__structai.pdf.__file__ 用于定位安装包源码文件。
  • 源码只用于阅读和定位问题,不要改源码,不要直接修改 site-packages 或共享环境;需要改库时,先 clone https://github.com/black-yt/structai,在用户确认后用 editable install。
python3 - <<'PY'
import inspect
import structai
import structai.pdf as pdf_mod
from structai import read_pdf

print("structai:", structai.__file__)
print("structai.pdf:", pdf_mod.__file__)
print("signature:", inspect.signature(read_pdf))
print(inspect.getsource(read_pdf))
PY

如果要继续追 read_pdf 调用的内部函数,先查看 structai.pdf 模块源码路径,再按函数名读取:

python3 - <<'PY'
import inspect
import structai.pdf as pdf_mod

print(pdf_mod.__file__)
for name in ["get_headers"]:
    obj = getattr(pdf_mod, name, None)
    if obj is not None:
        print(f"\n===== {name} =====")
        print(inspect.getsource(obj))
PY

MinerU Token

structai.read_pdf 会调用 MinerU 精准解析 API。该 API 需要 Token,且请求头格式为 Authorization: Bearer <Token>

获取方式:

  1. 打开 https://mineru.net/
  2. 注册或登录账号。
  3. 进入 API / Token 管理页面,免费申请 API Token。
  4. 把 Token 设置为环境变量 MINERU_TOKEN

Linux / macOS / WSL:

export MINERU_TOKEN="your_mineru_token"

Windows PowerShell:

$env:MINERU_TOKEN = "your_mineru_token"

验证环境变量是否已设置:

python3 -c "import os; print('MINERU_TOKEN set:', bool(os.environ.get('MINERU_TOKEN')))"

验证 structai 能读到 Token:

python3 -c "from structai.pdf import get_headers; h=get_headers(); print(h['Authorization'][:16] + '...')"

不要把真实 Token 写进代码、文档、Git 仓库或聊天记录。需要长期生效时,把 export MINERU_TOKEN=... 放到自己的 shell 配置文件或系统环境变量中。

如果未设置 Token,structai.read_pdf 会报类似错误:

MINERU_TOKEN not found. Please register a free account at https://mineru.net/ and set the environment variable.

为了避免解析时生成 __pycache__,建议运行命令时加上:

PYTHONDONTWRITEBYTECODE=1

基本解析

当前 structai.read_pdf 封装使用 MinerU 批量本地文件上传接口 /api/v4/file-urls/batch,适合解析本地 PDF 文件。MinerU 官方文档说明:精准解析 API 需要 Token,支持表格和公式识别,单个文件大小上限为 200 MB,页数上限为 200 页;批量上传接口单次申请上传链接不能超过 50 个文件。

如果 PDF 超过接口限制,先按页拆分或压缩,再分别解析。

Python 调用:

from structai import read_pdf

result = read_pdf("paper.pdf")

命令行解析:

env PYTHONDONTWRITEBYTECODE=1 python3 -c "from structai import read_pdf; read_pdf('paper.pdf')"

带摘要输出:

env PYTHONDONTWRITEBYTECODE=1 python3 -c "from structai import read_pdf
p='paper.pdf'
r=read_pdf(p)
print('success', bool(r))
if r:
    print('path', r['path'])
    print('text_length', len(r['text']))
    print('image_count', len(r['img_paths']))
    print(r['text'][:1200])"

本地解析结果

paper.pdf 调用 read_pdf 后,通常会在 PDF 同级位置生成同名目录:

paper/
  full.md
  layout.json
  *_content_list.json
  图片资源子目录

常用文件:

  • full.md:解析后的全文 Markdown。
  • layout.json:版面结构信息,可用于排查版面解析问题。
  • *_content_list.json:内容块列表,可辅助定位段落、标题、表格和图片。
  • 图片资源子目录:保存从 PDF 中抽取出来的图片或版面切片。

如果同名目录下已经存在 full.mdread_pdf 会优先复用本地解析结果,并直接读取本地 Markdown 和图片路径;这种情况下重复调用不会再次把同一个 PDF 上传到 MinerU。因此不用担心为了获取返回值而重复调用 read_pdf("paper.pdf") 会产生重复上传。只有删除本地解析目录、缺失 full.md、更换 PDF 路径或替换原始 PDF 后,才需要重新上传解析。

实际阅读时仍建议直接打开 full.md,这样最快,也方便手工检查解析质量。

返回值结构

成功时通常返回:

{
    "path": "paper.pdf",
    "text": "...",
    "img_paths": [...],
    "imgs": [...]
}

字段含义:

  • path:原始 PDF 路径。
  • textfull.md 的全文内容。
  • img_paths:Markdown 正文实际引用到的图片路径。
  • imgs:对应的 PIL 图片对象。

读取与检查

读取开头:

sed -n '1,120p' paper/full.md

查看标题结构:

rg -n "^#|^##|^###" paper/full.md

查看图片引用:

rg -n "!\\[" paper/full.md

至少确认:

  • full.md 存在且非空。
  • 标题、摘要、章节标题基本可读。
  • 图表引用能对应到本地图片资源。
  • 关键表格没有严重错行。
  • 公式和特殊符号没有影响理解。

常见问题

  • MINERU_TOKEN not found:先到 https://mineru.net/ 申请 Token,再设置 MINERU_TOKEN 环境变量。

  • 401403Authorization 相关错误:检查 Token 是否复制完整、是否过期、当前 shell 是否能读取 MINERU_TOKEN

  • 解析返回 None:确认 Token 已设置;关闭代理重试;检查是否已有可读 full.md;如果仍失败,记录错误信息。

  • Markdown 局部乱码或断词:用 full.md 快速定位章节,对关键段落、公式和表格回到 PDF 原文或抽取图片核对。

  • 图片目录文件很多:优先看 Markdown 中实际引用的图片,再按后续任务需要浏览其他图片。

  • 网络问题与代理处理:MinerU 处理和结果下载需要网络。如果遇到 SSLErrorUNEXPECTED_EOF_WHILE_READINGMax retries exceededConnection reset、上传成功但结果压缩包下载失败等问题,优先关闭代理后重试。关闭代理时仍要保留 MINERU_TOKEN

    env -u HTTP_PROXY -u HTTPS_PROXY -u ALL_PROXY -u http_proxy -u https_proxy -u all_proxy -u NO_PROXY -u no_proxy MINERU_TOKEN="$MINERU_TOKEN" PYTHONDONTWRITEBYTECODE=1 python3 -c "from structai import read_pdf; read_pdf('paper.pdf')"
    

    处理顺序:

    1. 保留当前目录,不要删除已经生成的解析缓存。
    2. 确认 MINERU_TOKEN 已设置。
    3. 用关闭代理的命令重试同一个 PDF。
    4. 如果重试成功,后续直接读取本地 full.md
    5. 如果重试失败但已有可读 full.md,直接使用本地 Markdown。
    6. 如果没有 full.md,记录完整错误信息,稍后重试或更换网络环境。

Signals

GitHub stars
53
Forks
4
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
pdf-parsing
Source
github.com/jokull/icelandic-data