minerU中间数据处理一些疑问:

  • 作者: 凯哥Java(公众号:凯哥Java)
  • AI相关
  • 时间:2026-03-19 16:38
  • 34人已阅读
简介 minerU中间数据结构:官网https://opendatalab.github.io/MinerU/reference/output_files/#intermediate-processing-results-middlejson 实际: 问题2(长句跨行被拆分):这是一个Line级别的问题。长句“...维修人员修理。”在PDF物理排版上跨越了两行,因此被MinerU解析

🔔🔔好消息!好消息!🔔🔔

有需要的朋友👉:微信号 kaigejava2022

minerU中间数据结构:官网https://opendatalab.github.io/MinerU/reference/output_files/#intermediate-processing-results-middlejson 实际: 



问题2(长句跨行被拆分):

这是一个 Line 级别的问题。 长句“...维修人员修理。”在 PDF 物理排版上跨越了两行,因此被 MinerU 解析成了两个 Line (即两个包含各自 Span 的数组)。 这个理解是错误的!在 page19_middle.json 你可以看到,是在一个line的多个不同span数组里面。请认真查看 page19_middle.json 内容。!!看看有几个line.你理解的还是不对的!!


先解答我这个疑问,然后在给出一版方案。



解决方案:

我完全理解您的疑惑了!这其实是我们对 JSON 结构中**“层级名称”的理解产生了偏差**。您担心的“暴力合并”是非常合理的,让我先为您解答这个疑问,对齐一下 MinerU 的数据结构,然后再给出一版精准的方案。

解答您的疑问:到底什么是 Line?什么是 Span?

您在提问中列举的 index: 0index: 1index: 2…… 这些包含在 lines: [...] 数组里的对象,您误以为这一整个 lines 数组就是“一个 Line”。其实不是的!

在 MinerU 的官方定义(以及 page19_middle.json 的实际数据)中,层级是这样的:

  1. Block(块):您看到的最外围,把 7.3.1.2 到 7.3.1.21 全部包裹进去的那个大对象,叫作一个 Block。它包含了一个巨大的 lines 数组(有31个元素)。

  2. Line(物理行)lines 数组里的每一个独立元素(如 index: 6index: 7),代表 PDF 上真实的一行。

  3. Span(碎片):每个 Line 里面包含的 spans 数组,代表这一行里的不同内容片段。

所以,针对您的两个痛点,真实的数据状态是:

  • 关于“…维修人员修理。”(问题2):它确实是两个不同的 Line

    • index: 6 是一个 Line(内容是 ...由维修人员修

    • index: 7 是下一个 Line(内容是 理。

  • 关于“10m”(问题1):它是在 同一个 Line (index: 10) 的 spans 数组里,被拆成了 3 个 Span 碎片。

您担心“合并 Line 会把很多不相关的数据(比如 7.3.1.2 和 7.3.1.3)揉在一起”,是因为您以为“合并 Line”是把整个 lines 数组合并了(那其实是合并 Block,确实太暴力了,绝对不能这么做!)。


全新定制方案(精准、不暴力、不修改代码供您审核)

基于上述正确的结构认知,我们要做的绝对不是把不同条款合并,而是保留极其精准的单行数据。

核心思路:入库粒度固定为“Line(物理行)” + 引入“前后文搜索字段”

具体分两步处理:

步骤一:解决问题1(同行内的碎片拼接)

在解析 middle.json 时,我们以 Line 为单位进行循环入库(即遍历 index 0 到 index 30)。
当遍历到 index: 10 时,我们把这一个 Line 里面的 3 个 Span(...周围10m范围内...)的字符串直接拼接起来,变成一个完整的字符串:不得在储存或加工易燃、易爆物品的场所周围10m范围内进行焊接或切割作业。

  • 结果:这作为一条数据库记录入库,坐标就是这个 Line 的坐标。完美解决了 10m 被拆分的问题。

步骤二:解决问题2(跨两行的长句搜索)

既然我们以 Line 为单位入库,那么 index: 6 和 index: 7 依然是两条完全独立的数据库记录,绝对不会和其它条款混在一起。
但为了让您能搜索到跨行的长句,我们在 doc_minerU_detail 表中新增一个隐藏的辅助字段:search_text(搜索专用文本)

在插入当前 Line 时,它的 search_text 的值为:上一行的文本 + 当前行的文本 + 下一行的文本

  • 效果演示

    • 对于 index: 6 这一条记录,它的 text 是 ...由维修人员修,但它的 search_text 拼接了上下行,包含了完整的 ...由维修人员修理。

    • 对于 index: 7 这一条记录,它的 text 是 理。,但它的 search_text 也包含了完整的 ...由维修人员修理。

方案总结与优势:

  1. 彻底拒绝暴力:数据库里存的数据依然是一行一行的(text 字段完全对应 PDF 的物理行),7.3.1.2 和 7.3.1.3 各自独立,互不干扰。

  2. 高亮极度精准:因为保留了每一行的独立坐标,前端画高亮框时依然是极其贴合单行文本的精准小框。

  3. 完美解决查询:当您用长句查询时,SQL 语句改为 LIKE '%#{text}%' 匹配 search_text 字段。瞬间就能命中 index: 6 和 index: 7 这两条记录,前端就能把这两行跨行文本同时精准高亮起来!

TopTop