Doc2X API v3 JSON 输出说明
基础说明
v3 JSON 不是新的独立接口,而是同一个解析链路在 v3-2026 模型下的扩展输出:
- 通过
POST /api/v2/parse/preupload创建任务时传入model: "v3-2026" - 通过
GET /api/v2/parse/status轮询任务状态 - 当
status=success时,除了原有的page.md之外,还会返回page.layout.blocks
相较于传统只关注 md 的结果,v3 JSON 会额外给出:
- block 级别的结构化内容
- block 之间的父子关系
- 页内阅读顺序
- 图片 block 的裁切图片 URL
- 表格 block 的 HTML 内容
启用方式
可以通过下面的完整请求启用 v3-2026 模型:
curl --location --request POST 'https://v2.doc2x.noedgeai.com/api/v2/parse/preupload' \
--header 'Authorization: Bearer sk-xxx' \
--header 'Content-Type: application/json' \
--data-raw '{
"model": "v3-2026"
}'拿到返回的 uid 和上传用 url 后,使用 PUT 上传文件,再通过 GET /api/v2/parse/status?uid=... 轮询结果。
返回结构概览
顶层字段
| 字段 | 类型 | 含义 |
|---|---|---|
code | string | 请求状态,成功时为 success |
data.status | string | 任务状态,常见值为 processing、failed、success |
data.progress | int | 任务进度,范围 0~100 |
data.result.version | string | 版本字段,当前样例中为空字符串,可视为预留字段 |
data.result.pages | array | 逐页解析结果 |
page 字段
| 字段 | 类型 | 含义 |
|---|---|---|
page.url | string | 页级图片 URL,当前样例中为空字符串 |
page.page_idx | int | 页码,从 0 开始 |
page.page_width | int | 页面宽度,单位像素 |
page.page_height | int | 页面高度,单位像素 |
page.md | string | 本页 Markdown 文本 |
page.score | int | 本页质量分,范围 0~100 |
page.layout.blocks | array | 本页结构化 block 列表 |
返回示例
下面的示例基于真实 v3 返回结果做了截断,保留了 md、blocks、attributes、linking 等关键结构。
{
"code": "success",
"data": {
"status": "success",
"progress": 100,
"result": {
"version": "",
"pages": [
{
"url": "",
"page_idx": 0,
"page_width": 1753,
"page_height": 2338,
"md": "<!-- Meanless: Water Research 264 (2024) 122255... -->\n\n# Non-radical oxidation driven by iron-based materials...",
"score": 85,
"layout": {
"blocks": [
{
"id": "blk_p0_0",
"type": "Text",
"text": "Water Research 264 (2024) 122255",
"bbox": [699, 98, 1046, 132],
"reading_order": 0,
"parent_id": "",
"src": "",
"attributes": {
"is_boilerplate": true
}
},
{
"id": "blk_p0_7",
"type": "Title",
"text": "Non-radical oxidation driven by iron-based materials without energy assistance in wastewater treatment",
"bbox": [101, 480, 1343, 585],
"reading_order": 7,
"parent_id": "",
"src": ""
},
{
"id": "blk_p0_21",
"type": "Text",
"text": "The persistence of organic pollutants in aquatic environments presents a significant risk to human health...",
"bbox": [103, 1486, 858, 1924],
"reading_order": 21,
"parent_id": "",
"src": "",
"linking": {
"prev_block_id": "",
"next_block_id": "blk_p0_22"
}
},
{
"id": "blk_p0_24",
"type": "FootnoteGroup",
"text": "",
"bbox": [101, 1964, 1242, 2042],
"reading_order": 24,
"parent_id": "",
"src": ""
}
]
}
}
]
}
}
}表格 block 的返回示例如下:
{
"id": "blk_p2_2",
"type": "TableGroup",
"text": "",
"bbox": [101, 156, 1649, 907],
"reading_order": 2,
"parent_id": "",
"src": ""
}{
"id": "blk_p2_5",
"type": "Table",
"text": "",
"bbox": [101, 217, 1649, 819],
"reading_order": 4,
"parent_id": "blk_p2_2",
"src": "",
"table_data": {
"html": "<table><tr><td rowspan=\"2\">Review</td><td rowspan=\"2\">Iron-based materials</td><td colspan=\"5\">Oxidation systems</td>...</tr></table>"
}
}block 通用字段说明
| 字段 | 类型 | 含义 |
|---|---|---|
id | string | block 唯一标识,当前样例格式类似 blk_p2_5 |
type | string | block 类型,例如 Text、Title、Table |
text | string | block 的文本内容;当前样例中 group、figure、table 通常返回空字符串 |
bbox | int[4] | 绝对坐标,格式为 [x1, y1, x2, y2] |
reading_order | int | 页内阅读顺序,从 0 开始;group 类 block 始终与其第一个子 block 共享同一个顺序值 |
parent_id | string | 父级 group 的 id;当前样例里无父节点时返回空字符串 |
src | string | 图片资源 URL;非图片类 block 一般返回空字符串 |
linking | object | 逻辑上属于同一内容但被拆到多个 block、栏或页时使用的链接信息 |
attributes | object | block 额外属性,仅在有属性时出现 |
table_data | object | 仅 Table block 出现;当前样例中包含 html |
linking 字段
linking 用于表达“这些 block 在逻辑上应该连起来看”,基本结构如下:
{
"prev_block_id": "blk_p0_21",
"next_block_id": "blk_p0_22"
}当前样例里,prev_block_id 或 next_block_id 不存在时使用空字符串。
linking 常见有下面三种场景:
- 跨栏、跨页的文字段落拼接
- 典型对象是
Text。 - 当一个长段落在双栏排版里被拆开,或者从当前页延续到下一页时,可以用
prev_block_id/next_block_id把这些正文块串起来。
- 跨栏、跨页的表格拼接
- 典型对象是
Table。 - 一般来说只有
Table会带linking,TableGroup通常不带。 - 当一个逻辑上的完整表格因为版面原因被拆到不同栏位或不同页面时,可以通过
linking把前后表格块关联起来。
- 目录中“目录条目”和“目录页码”的拼接
- 典型对象是目录相关 block,例如
TOCGroup内的文本块。 - 当目录标题文字和对应页码被识别成两个独立 block 时,可以通过
linking表示它们属于同一个目录项。
block 类型说明
下面按“一般类别”和 “Group 类别”分开说明。部分类型已经在当前样例中出现,部分是按 v3-json 设计预留、可能在其他文档中出现。
一般类别
| 类型 | 含义 | 典型特征 |
|---|---|---|
Text | 文本段,包括普通正文段、普通 OCR 文本段、页眉页脚文本段等 | 可能带 attributes 或 linking |
Title | 标题,包括论文标题、章节标题等 | 通常是独立标题块 |
Caption | 图注、表注、补充说明文字 | 往往挂在 FigureGroup 或 TableGroup 下 |
Figure | 图片本体 | src 通常不为空,parent_id 指向 FigureGroup |
Table | 表格本体 | table_data.html 返回表格 HTML |
Equation | 公式正文 | 常挂在 EquationGroup 下 |
EquationNumber | 公式编号 | 如 (1)、(2) |
Underline | 独立下划线 block | 常见于被单独识别出的下划线元素 |
Code | 代码块或伪代码块本体 | 常见于代码区域本体 |
Group 类别
| 类型 | 含义 | 典型特征 |
|---|---|---|
FigureGroup | 图片组 | 一般包含 Figure 和一个或多个 Caption |
TableGroup | 表格组 | 一般包含 Table 和一个或多个 Caption |
EquationGroup | 公式组 | 一般包含 Equation,可能包含 EquationNumber |
FootnoteGroup | 脚注组 | 页脚脚注区域的容器 |
ReferenceGroup | 参考文献组 | 文末参考文献区域的容器 |
TOCGroup | 目录区域容器 | 常用于组织目录条目与对应页码 |
CodeGroup | 代码块及其描述文字的父级容器 | 常用于组织代码与说明文字 |
SideGroup | 侧栏、旁注、aside 区域容器 | 常用于组织边栏内容 |
下面是各类 block 的具体说明。
Text
- 文本段 block。
- 普通正文段、页眉页脚文本段、页码文本段等都可能以
Text返回。 - 页眉、页脚、页码等样板文字也会以
Text返回,但通常会附带attributes.is_boilerplate=true。 - 当一段内容被跨栏、跨页或被切分时,可能出现
linking。
Title
- 标题块。
- 常见于文档标题、一级标题、二级标题等结构化标题。
Caption
- 图、表等媒体对象的描述文字。
- 常见于
FigureGroup或TableGroup的子节点。
Figure
- 图片本体。
src为图片裁切后的 URL。- 当前样例中
text为空字符串。
Table
- 表格本体。
- 通过
table_data.html返回表格 HTML。 - 当一个逻辑表格被拆到不同栏位或不同页面时,可能出现
linking。
Equation
- 公式本体。
- 当前样例中公式内容以字符串形式放在
text中。
EquationNumber
- 公式编号。
- 通常和
Equation一起挂在同一个EquationGroup下。
FigureGroup
- 图片组容器。
- 一般用于把图片本体和图注组织为一个父级 block。
TableGroup
- 表格组容器。
- 一般用于把表格本体和表注组织为一个父级 block。
TOCGroup
- 目录区域容器。
- 目录条目和对应页码如果被识别成多个 block,可以通过
linking进行关联。
EquationGroup
- 公式组容器。
- 一般用于多行公式或带编号公式的父级组织。
FootnoteGroup
- 脚注区域容器。
- 当前样例中
text为空字符串,具体内容由该区域内其他 block 或md呈现。
ReferenceGroup
- 参考文献区域容器。
- 通常用于组织文末连续的参考文献条目。
attributes 字段说明
| 属性名 | 类型 | 含义 |
|---|---|---|
is_boilerplate | bool | 样板文字,通常用于页眉、页脚、页码、重复出版信息等,一般建议去除 |
writing_mode | string | 文字书写方向,例如横排或竖排 |
rotation | int | 相对于默认文字 0 度方向的顺时针旋转角度,常见值为 90、180、270 |
is_boilerplate
用于标记重复的、标准化的、非正文主体的信息,例如:
- 页眉
- 页脚
- 页码
- DOI、出版时间等固定出版信息
- 该标记的识别结果往往不一定完全准确,调用方一般可按可丢弃信息处理
- 在
md中,这类内容通常会被包裹在<!-- Meanless: ... -->这样的 HTML 注释中
示例:
{
"type": "Text",
"text": "Received 23 May 2024; Received in revised form 22 July 2024; Accepted 11 August 2024",
"attributes": {
"is_boilerplate": true
}
}writing_mode
用于表达书写方向,主要是为竖排文档预留。建议调用方按字符串枚举兼容,常见设计值包括:
horizontal-tb:默认横排vertical-rl:一般用于古文、日语等从右向左、从上往下书写的情况
rotation
用于描述 block 的视觉旋转角度,表示相对于默认文字 0 度方向的顺时针旋转角度,主要对 Text / Caption 有意义。建议调用方按整数角度兼容:
0:默认不旋转90180270
table_data 字段说明
table_data 只会出现在 Table block 上。
字段说明
| 字段 | 类型 | 含义 |
|---|---|---|
html | string | 当前表格的 HTML 内容 |
示例:
{
"table_data": {
"html": "<table><tr><td>Quencher</td><td>...</td></tr></table>"
}
}基于 JSON 提取 PDF 内图表和表格图片
如果你希望把 v3 JSON 中识别出的图、表进一步裁剪成独立图片,可以直接基于 page.layout.blocks 里的 bbox,配合每页的 page_width / page_height,从原始 PDF 中重新渲染并裁切。
pdfdeal 里已经提供了现成的辅助能力:
extract_v3_figure_images:提取Figureblock 对应的图片extract_v3_table_images:提取Tableblock 对应的图片scripts/extract_v3_figures.py:命令行提取 figure 图片scripts/extract_v3_tables.py:命令行提取 table 图片
实现思路
整体流程如下:
- 读取
v3 JSON,拿到pages - 在每页
layout.blocks中筛选Figure或Table - 使用 block 的
bbox和 page 的page_width/page_height建立页面坐标到渲染像素坐标的映射 - 按指定
dpi渲染包含目标 block 的 PDF 页面 - 根据映射后的裁剪框输出独立 PNG,并生成
manifest.json
这套流程适合:
- 从
Figureblock 提取原始 PDF 中的图像区域 - 从
Tableblock 提取表格截图 - 在本地落盘统一管理图表图片,而不是只使用 JSON 中的结构信息
命令行示例
下面的脚本来自 pdfdeal 仓库的 scripts/ 目录:
pdfdeal/scripts/extract_v3_figures.pypdfdeal/scripts/extract_v3_tables.py
提取图图片:
python scripts/extract_v3_figures.py \
--pdf /path/to/input.pdf \
--v3-json /path/to/input_v3.json \
--dpi 200 \
--output-dir ./Output/figures提取表格图片:
python scripts/extract_v3_tables.py \
--pdf /path/to/input.pdf \
--v3-json /path/to/input_v3.json \
--dpi 200 \
--output-dir ./Output/tablesPython 示例
from pdfdeal import extract_v3_figure_images, extract_v3_table_images
figure_summary = extract_v3_figure_images(
pdf_path="/path/to/input.pdf",
v3_json_path="/path/to/input_v3.json",
dpi=200,
output_dir="./Output/figures",
)
table_summary = extract_v3_table_images(
pdf_path="/path/to/input.pdf",
v3_json_path="/path/to/input_v3.json",
dpi=200,
output_dir="./Output/tables",
)
print(figure_summary["crop_count"], figure_summary["manifest_path"])
print(table_summary["crop_count"], table_summary["manifest_path"])输出内容
输出目录通常包含:
_pages/:被渲染的整页 PNG- 若干裁剪后的
figure或tablePNG manifest.json:记录每个裁剪结果对应的page_idx、block_id、block_xyxy、crop_box_pixels和输出路径
manifest.json 适合继续用于:
- 建立 block 和本地图片文件的映射
- 后续多模态检索或图表二次处理
- 调试裁剪位置是否和
v3 JSON一致
调用方兼容建议
建议调用方按下面的方式兼容 v3 JSON:
- 继续把
page.md作为可直接展示或导出的正文结果。 - 把
page.layout.blocks作为结构化增强层,而不是替代md。 - 认为
type、attributes、table_data都是可扩展字段,避免写死枚举外即报错。 - 对空字符串保持兼容:当前样例中
parent_id、src、linking.prev_block_id、linking.next_block_id都可能是空字符串。 - 对 group 类 block 保持兼容:当前样例中 group block 的
text不是null,而是空字符串。