unstructured DOCX无法识别文本框内的列表项

ubby3x7f  于 2个月前  发布在  其他
关注(0)|答案(7)|浏览(40)

描述bug

DOCX无法识别Word文档中文本框元素内的列表项

重现方法

提供一个包含两种列表项的示例Word文件。
如上图所示,只有"普通"列表项被识别,而文本框内的列表项从元素列表中丢失。
list_in_texbox_list-item-missing.docx

截图

qhhrdooz

qhhrdooz1#

这是文件内容:

vs3odd8k

vs3odd8k2#

@scanny -对此有什么看法?

qco9c6ql

qco9c6ql3#

我们目前从内联文本框形状中提取运行文本,以及与文本框锚定的段落中的其余文本。这种行为是在这篇PR中添加的:#2510
我们可以以不同的方式进行操作,使得内联和浮动文本框分别分区,这样它们就会将其中的列表项识别为单独的元素。

背景

  • 运行(run)是一个段落内的内联元素(想想HTML <span>)。段落文本只能出现在运行中。段落文本是其每个运行文本的连接。
  • (DOCX)形状包含几种可能的“图形”项目之一,包括一个文本框,但也可以是图像、图表、智能艺术等。
  • 文本框形状包含一个或多个段落。通常,文档中的每个非空段落都会在输出中产生一个单独的元素。
  • 形状可以是内联浮动。内联形状被视为一个大字符,并随着段落文本的流动而流动。浮动形状锚定到一个段落,但可以移动到任意位置,文本围绕它流动。

先前PR中采用的方法是将内联文本框中的任何文本与出现它的段落的文本一起包含。

  • 由于这仅适用于内联形状,而示例是浮动的,因此“Aaa...”文本不会出现在分区输出中。
  • 如果它是一个内联文本框,所有文本将一起出现在一个单一元素中,如text="AaaBbbccc",因为这是文本框中所有运行的连接,而它出现的段落是空的。
  • 如果我们想要更精确地分区文本框形状,我们需要添加一个子分区器,该子分区器会单独考虑文本框中的段落,每个段落都会产生自己的元素。在这种情况下,段落被识别为列表项,因此文本框会产生三个ListItem元素,这些元素紧跟在包含段落中其他文本的元素之后(在这个特定的情况下为空)。
vfhzx4xs

vfhzx4xs4#

@scanny - 如果我有多个文档在这个结构中(里面有很多文本的浮动形状),有什么建议或解决方法吗?

7xllpg7q

7xllpg7q5#

@veredmm 不是凭空想出来的,不是。通用解决方案对当前的分区器结构(所以不容易进行猴子补丁或其他操作)会产生很大的干扰,并且需要深入了解DOCX格式的领域知识。

然而,如果你将以下这行代码:
https://github.com/Unstructured-IO/unstructured/blob/main/unstructured/partition/docx.py#L441
从:

"w:r | w:hyperlink | w:r/descendant::wp:inline[ancestor::w:drawing][1]//w:r"

改为:

"w:r"
" | w:hyperlink"
" | w:r/descendant::wp:inline[ancestor::w:drawing][1]//w:r"
" | w:r/descendant::wp:anchor[ancestor::w:drawing][1]//w:r"

(注意 wp:anchor (浮动形状)和 wp:inline (内联形状))
那么文本框内的文本至少会在输出中显示出来。
它不会很美观,因为段落文本在没有空格的情况下会被连接在一起,例如:

  • the quick brown fox
  • jumped over the lazy dog

会显示为:
"whatever text came beforethe quick brown foxjumped over the lazy dogwhatever text came after"
所以你需要判断这样做的好处是否值得麻烦。

rt4zxlrg

rt4zxlrg6#

感谢!但是我想知道为什么不在join语句中添加一个空格来防止单词连接:
text = " ".join(
e.text
for e in paragraph._p.xpath(
"w:r"
" | w:hyperlink"
" | w:r/descendant::wp:inline[ancestor::w:drawing][1]//w:r"
" | w:r/descendant::wp:anchor[ancestor::w:drawing][1]//w:r"
)
)

1tu0hz3e

1tu0hz3e7#

可以做到,但这会在常规运行之间增加额外的空间,而这些常规运行已经包含了它们所需的空间。

相关问题