【问题标题】:Line order in PDF seems to be randomly scrambledPDF 中的行顺序似乎是随机打乱的
【发布时间】:2017-07-26 20:48:42
【问题描述】:

我有两个 PDF 文件必须用 iTextSharp 解析(因为我们没有用于构建该 PDF 的源数据)。

我能够在 C# 中构建一个解析过程,它可以逐行解析第一个 PDF。同样的过程应该适用于第二个文件,但不幸的是它没有,因为第二个 PDF 中的行顺序完全被破坏了,并且与视觉结构不同。

奇怪的是,不仅 iTextSharp 会这样解释第二个文件,甚至 Acrobat Reader DC 的文本选择工具也无法以正确的行顺序选择信息(当我开始选择行时,一些文本仍然未被选中并得到在插入符号到达接下来的几行之后突出显示)。

第一个 PDF 中的文本选择(在 Acrobat Reader DC 中)

第二个 PDF 中的文本选择(在 Acrobat Reader DC 中)

基本上每条信息(一个单词或一个短语)都放在它自己的行上 (!)。有些单词/短语实际上是在页面底部阅读的,而它们显然在顶部附近等

如何正确修复/阅读第二个 PDF?任何想法该文件发生了什么?

更新

为两个 PDF 文件添加链接

【问题讨论】:

  • 为什么您会觉得奇怪的是,两个 PDF 阅读器会以相同的方式处理同一个 PDF?直觉上,这是人们所期望的。如果他们以不同的顺序读取文件,可能会被认为很奇怪。 (特别是因为顺序可能对应于文件本身的文本顺序。)

标签: c# parsing pdf itext text-parsing


【解决方案1】:

PDF 本身不知道“行”或“段落”等。

如果您有一个结构化的 PDF,您可以使用该结构来确定哪些内容属于一起。

如果不是,您将不得不读出文本片段的边界框,并使用一些启发式方法来确定哪些内容属于一起。

【讨论】:

  • 这正是我对第一个 PDF 文件所做的。我创建了一个自定义 iTextSharp 的文本提取策略,使用块之间的距离将页面读取为块(门图像 + 图像下方的行 + 右边缘的尺寸)。然而,第二个 PDF 只是一堆由单个单词组成的行,以随机顺序阅读。只要看看我的问题中的图像,您多久会看到文本选择这样的 PDF?只需用 Google 搜索 PDF,打开它并尝试从中选择一些文本,它可能会允许您以正确的顺序逐字选择文本行
  • 您是否(手动)使用了 Alt-Drag(我认为在 Windows 上就是这样;在 Mac 上是 Option-Drag)?当然,如果您必须以编程方式执行此操作,这将无济于事。
  • 你可以使用鼠标,Alt+鼠标拖动,Shift+PgDown等,没关系。我想说的是 iTextSharp 和 Acrobat Reader DC 都以相同(无序)的方式阅读第二个 PDF。引用:The strange thing that not only iTextSharp is interpreting the second file like that, even Acrobat Reader DC's text selection tool fails to select the information with a correct line order
  • @Salaros 你说你创建了一个自定义文本提取策略,但你没有展示它。因此,我们无法分析为什么它会这样做。但是,Adobe Reader 在文本提取(复制和粘贴)期间在一定程度上考虑了在页面上绘制字符串的顺序(这可能与您作为人类在文档中感知的顺序完全不同)。通常 PDF 创建程序会按照人类理解的顺序添加绘图指令,但有时(尤其是在编辑 PDF 之后)在复制和粘贴时会以有趣的结果打乱这些绘图指令。
【解决方案2】:

@Max 已经回答了,

PDF 本身不知道“行”或“段落”等。

尤其是文本绘制指令在页面内容流中出现的顺序可以是逐行的顺序,使文本提取和分析变得容易,但它也可以是半随机的、完全不直观的顺序。

我会充实他的答案。

示例 PDF

如果是您的 PDF,您可以查看这两个选项的示例,“HUTTIG - ThermaTru JAN2016.pdf”第 7 页上的文本位按此顺序绘制

Glass & Caming Options Door Only Pricing Classic-Craft®
LE - Low - E A-Brass For Prehung Units see:
FXG-Fixed Grille C-Brushed Nickel Frame Adder and Options Pages
RG-Removable Grille D-Black Nickel Pricing Valid only when Prehung
SDL-Simulated Divide Lite
GBGF-Flat(W,B,A) Grille In Glass
GBGC-Cntr(W,B,A) Grille In Glass
W-Wrought Iron For Additional Options See Adder Page
?=Stock s=Rapid Ship
American Collection™
~~CCA210 ~~CCA210XC ~~CCA210XJ ~~CCA210XN ~~CCA210XR ~~CCA211
1 CCA210-LE CCA210XC CCA210XJ CCA210XN CCA210XR CCA211
Low-E Chord Chinchilla Granite Rainglass Homeward C D
2'8" x 6'8"
2'10" x 6'8"
3'0" x 6'8" $582.67 ? $865.22 ? $898.90 $898.90 $898.90 $923.30 ??
3'6" x 6'8"
Slab CANF3026L1L CANF3026DXC CANF3026DXJ CANF3026DXN CANF3026DXR CANF3026D1HW1C
Insert
Grille
~~CCA212 ~~CCA220 ~~CCA220XC ~~CCA220XJ ~~CCA220XN ~~CCA220XR
1 CCA212 CCA220-SDLLE CCA220XC-SDL CCA220XJ-SDL CCA220XN-SDL CCA220XR-SDL
Villager C D SDL Low-E SDL Chord SDL Chinchilla SDL Granite SDL Rainglass
2'8" x 6'8"
2'10" x 6'8"
3'0" x 6'8" $1,176.57 $641.72 ? $924.27 ? $957.94 $957.94 $957.94
3'6" x 6'8"
Slab CANF3026D1VG1C CANF3026L1L CANF3026DXC CANF3026DXJ CANF3026DXN CANF3026DXR
Insert
Grille CCALD2618V24 CCALD2618V24 CCALD2618V24 CCALD2618V24 CCALD2618V24
~~CCA221 ~~CCA222 ~~CCA230 ~~CCA230XC ~~CCA230XJ ~~CCA230XN
1 CCA221-SDL CCA222-SDL CCA230-SDLLE CCA230XC-SDL CCA230XJ-SDL CCA230XN-SDL
SDL Homeward C D SDL Villager C D SDL Low-E SDL Chord SDL Chinchilla SDL Granite
2'8" x 6'8"
2'10" x 6'8"
3'0" x 6'8" $1,042.37 ? $1,258.06 $701.26 ? $983.81 ? $1,017.48 $1,017.48
3'6" x 6'8"
Slab CANF3026D2HW1C CANF3026D2VG1C CANF3026L1L CANF3026DXC CANF3026DXJ CANF3026DXN
Insert
Grille CCALD2618V24 CCALD2618V24 CCALD2618V24 CCALD2618V24 CCALD2618V24 CCALD2618V24
March 2016 Confidential | Huttig Building Products | Prices Subject to Change Without Notice Page 7 of 814

如您所见,该顺序与我们阅读页面的顺序大致相同。

另一方面,“Huttig - 2017 Therma-Tru Catalog.pdf”第 7 页的文本位是按此顺序绘制的

Confidential | Prices Subject to Change Without Notice | Terms & Conditions: www.huttig.com/salesterms January 28,2017 Page 7 of 820
Glass & Caming Options Classic-Craft® Standard Single Unit Includes:

  LE - LOW - E
  FXG - Fixed Grille
  RG - Removable Grille
  SDL - Simulated Divide Lite
  GBGF - Flat(W,B,A) Grille In Glass
  GBGC - Cntr(W,B,A) Grille In Glass
  W - Wrought Iron
  SDLF1 - 1-1/8" SDL
  SDLF2 - 3-1/2" SDL
A - Brass
C - Brushed Nickel
D - Black Nickel
XC - Chord
XJ - Chinchilla
XN - Granite
XR - Rainglass
XE - Satin Etch
For Prehung Units See:
Frame Adders and Options Pages
Pricing Valid only when Prehung
For Additional Options See Adder Page
= Rapid = Stock
American Collection™
Slab
Grille

Chinchilla
$940.38 $906.22
CANF3026DXC
$940.38
CANF3026DXN
$940.38
CANF3026DXR
$967.22
CANF3026D1HW1D
CCA212 CCA220-SDLLE CCA220XJ-SDL CCA220XC-SDL CCA220XN-SDL CCA220XR-SDL
Villager SDL Low-E SDL Chinchilla SDL Chord SDL Granite SDL Rainglass
$1,231.71 $672.46
CCALD2618V24
$1,002.35
CCALD2618V24
$968.19
CCALD2618V24
$1,002.35
CCALD2618V24
$1,002.35
CCALD2618V24
CCA221-SDL CCA222-SDL CCA230-SDLLE CCA230XJ-SDL CCA230XC-SDL CCA230XN-SDL
SDL Homeward SDL Villager SDL Low-E SDL Chinchilla SDL Chord
$1,090.68
CANF3026D2HW1D
$1,316.62 $734.44 $1,064.82 $1,030.66 $1,064.82
SDL Granite
CANF3026DXJ
CCA210-LE
Low-E
CCA210XJ CCA210XC CCA210XN CCA210XR CCA211
Chord Rainglass Homeward
CCALD2618V24 CCALD2618V24 CCALD2618V24 CCALD2618V24 CCALD2618V24 CCALD2618V24
CANF3026D2VG1D CANF3026L1L CANF3026DXJ CANF3026DXC CANF3026DXN
CANF3026DXR CANF3026DXN CANF3026DXC CANF3026DXJ CANF3026L1L CANF3026D1VG1D
C  D
C  D C  D
Granite
CANF3026L1L
$610.00 3' 0" x 6'8"
3' 0" x 6'8"
3' 0" x 6'8"
Slab
Insert
Grille
Slab
Grille
Insert
     
Insert
 
C  D
 
Available
Available
Available

如您所见,第一张桌子的价格(最左边的 610 美元除外)很早就绘制出来了,然后是其他桌子的价格,然后是顶部 CCA 和底部 CANF 第一个表的标识符,然后是所有表的 C 和 D 列标题,然后是其他一些条目,然后是第一个表中缺少的 610 美元价格,然后是所有表的行标题,最后是出现在页面上但不可见的三个“可用”。

知道该文件发生了什么吗?

我可以推测。根据 PDF 的生产者属性,2016 年目录似乎是直接从 MS Excel 2010 导出的,而 2017 年目录是由 Ghostscript 创建的。此外,这些目录看起来相似但又足够不同,可以假设 2017 年的目录不是从同一个源 Excel 文件创建的,而是可能使用完全不同的工具链,其任务是生成与前者看起来相似的东西目录,而不是与它看起来相同的东西,更不用说与它内部构建相同的东西了。

如何处理

如何正确修复/阅读第二个 PDF?

首先,没有什么需要解决的:对于通用 PDF,不需要以任何特定顺序绘制文本。因此,第二个 PDF 没有损坏(至少在这方面没有损坏),因此无法修复。

要正确阅读和分析它,您必须按照@Max 的回答进行操作,

您必须读出文本片段的边界框,并使用一些启发式方法来确定哪些内容属于一起。

很遗憾,您尚未发布(关键部分)您的文本提取策略。如需更详细的帮助,请发布。

不过,考虑到您能够在 C# 中构建一个解析过程,它逐行解析第一个 PDF 而不是第二个文件 因为第二个 PDF 中的行顺序是完全损坏并且它与视觉结构不同,我假设您的自定义文本提取策略基于SimpleTextExtractionStrategy,因为它假设文本位以逐行顺序出现。最重要的是,它可能使用文本位坐标(至少是 x 坐标)来确定文本位出现的列。

逐行假设并不总是成立,尤其是在您的 2017 年目录中。因此,您应该根据LocationTextExtractionStartegy 代码重新实施您的策略,即首先从页面中收集所有文本位,包括其相关坐标(边界框、基线等),然后对这些位进行排序(顶部- to-bottom, left-to-right),然后执行您的附加逻辑来识别列。

【讨论】:

  • 首先,我已经在使用基于 LocationTextExtractionStrategy 的提取策略。它覆盖RenderText(TextRenderInfo renderInfo) 方法并获取线段并将它们转换为TextChunks 等。我已经尝试迭代线段/文本块并使用这些元素的坐标对它们进行排序,但我仍然需要弄清楚如何访问它们。您能否分享一下您用于获得上述结果的策略代码?
  • 另外在你的回答中你说The line-by-line assumption does not always hold,但如果它工作得很好,我只有8个门没有解析,800多个页面,每个包含至少12-18个元素。我使用文本块之间的距离来附加空格或制表符(1、2、3、4 甚至五个制表符),因此可以轻松地将生成的数据结构保存到 CSV 文件(制表符分隔)并作为 Excel 文件打开.
  • 如果您确实使用了基于LocationTextExtractionStrategy 的提取策略,那么这里的人可以说得更少,而不会看到您的启发式失败的原因。 我使用文本块之间的距离来添加空格或制表符 - 你肯定已经看到表格列在新文件中分散得更远。因此,如果制表符旨在分隔输出中的这些表列,您可能至少需要调整制表符插入的标准。
  • @Salaros “你能分享一下你用来获得上述结果的策略代码吗?” - 那是简单的SimpleTextExtractionStrategy(在2017 年输出)。
  • @Salaros 我刚刚应用了另一种文本提取策略(this answer 和 fixedCharWidth 中描述的那个从 6 减少到 4 以匹配目录中的小字体;它在 Java / iText但应该很容易将 C# / iTextSharp) 移植到您的 PDF,并且对于这两个文件,输出看起来应该很容易后处理为 CSV 数据。您可能想查看该策略以获取灵感。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-11
  • 2020-10-11
  • 2012-04-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多