Pdf parsing
徐望瀚日常工作中使用和维护的可复用 agent skills。
npx -y skills add black-yt/skills --skill pdf-parsingAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 6 stars6 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
当需要用 structai.read_pdf 将 PDF 文档解析成本地 Markdown、抽取图片资源,并处理 MinerU 解析缓存或代理重试问题时使用。
SKILL.md
8.4 KB, ~2.6k tokens by cl100k_base, as published. Nobody here has run it
PDF 解析
目标
把 PDF 文档解析成本地可读取、可搜索、可复制的 Markdown,并抽取 PDF 中的图片资源。解析完成后,后续阅读应优先使用本地 Markdown 文件;重复调用 structai.read_pdf 也会优先复用本地解析结果,不会在本地结果已存在时重复上传同一个 PDF。
依赖安装
当前 skill 对照的关键解析依赖:
structaipackage version:0.1.24。structaiGitHub 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,请确认 pip 和 python3 指向同一个环境:
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或共享环境;需要改库时,先 clonehttps://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>。
获取方式:
- 打开 https://mineru.net/。
- 注册或登录账号。
- 进入 API / Token 管理页面,免费申请 API Token。
- 把 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.md,read_pdf 会优先复用本地解析结果,并直接读取本地 Markdown 和图片路径;这种情况下重复调用不会再次把同一个 PDF 上传到 MinerU。因此不用担心为了获取返回值而重复调用 read_pdf("paper.pdf") 会产生重复上传。只有删除本地解析目录、缺失 full.md、更换 PDF 路径或替换原始 PDF 后,才需要重新上传解析。
实际阅读时仍建议直接打开 full.md,这样最快,也方便手工检查解析质量。
返回值结构
成功时通常返回:
{
"path": "paper.pdf",
"text": "...",
"img_paths": [...],
"imgs": [...]
}
字段含义:
path:原始 PDF 路径。text:full.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环境变量。 -
401、403或Authorization相关错误:检查 Token 是否复制完整、是否过期、当前 shell 是否能读取MINERU_TOKEN。 -
解析返回
None:确认 Token 已设置;关闭代理重试;检查是否已有可读full.md;如果仍失败,记录错误信息。 -
Markdown 局部乱码或断词:用
full.md快速定位章节,对关键段落、公式和表格回到 PDF 原文或抽取图片核对。 -
图片目录文件很多:优先看 Markdown 中实际引用的图片,再按后续任务需要浏览其他图片。
-
网络问题与代理处理:MinerU 处理和结果下载需要网络。如果遇到
SSLError、UNEXPECTED_EOF_WHILE_READING、Max retries exceeded、Connection 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')"处理顺序:
- 保留当前目录,不要删除已经生成的解析缓存。
- 确认
MINERU_TOKEN已设置。 - 用关闭代理的命令重试同一个 PDF。
- 如果重试成功,后续直接读取本地
full.md。 - 如果重试失败但已有可读
full.md,直接使用本地 Markdown。 - 如果没有
full.md,记录完整错误信息,稍后重试或更换网络环境。