如何迭代PDF页面中的所有对象并检查哪些是文本对象?

时间:2012-10-20 08:15:59

标签: python pypdf

我想使用pypdf迭代pdf页面中的所有对象。

我还想检查对象的类型是什么,无论是文本还是图形。

代码段将是一个很好的帮助。

非常感谢

2 个答案:

答案 0 :(得分:5)

我认为PyPDF不适合这项工作。你需要的是解析页面本身(对于PyPDF有限的支持,请参阅the API documentation),然后能够结果保存到另一个更改某些对象后的PDF对象。

您可以使用pdftk解压缩PDF,这样您就可以使用pdfrw了。

然而,根据你的写作,

  

我的最终目标是以不同方式为每个文本对象着色。

“文本对象”可以是由(例如)不同段落中的不同行组成的非常复杂的对象。这可能是,您可能会将其视为单个实体。在这个实体中,可能已经存在几种不同的文本颜色命令。

例如,您可能只有一个包含此文本序列的流(这是用“内部”语言编写的):

12.84 0 Td(S)Tj
0.08736 Tc
9 0 Td(e)Tj
0.06816 Tc
0.5 g
7.55999 0 Td(qu)Tj
0.08736 Tc
1 g
16.5599 0 Td(e)Tj
0.06816 Tc
7.55999 0 Td(n)Tj
0.08736 Tc
8.27996 0 Td(c)Tj
-0.03264 Tc
0.13632 Tw
7.55999 0 Td(e )Tj
0.06816 Tc
0 Tw

这可能会写“ Se qu ence ”。它实际上由七个文本子对象组成,并且没有我知道的库可以将流“解密”到其组件子对象中,更不用说为它们分配适当的属性(在PDF中从图形状态下降,而在任何层次结构中)诸如XML之类的结构可能与单个节点相关联,可能通过继承)。

更多:流可能包含非文本命令(例如行)。然后更改“文本”描边颜色实际上也会改变非文本对象的颜色

库应该为您提供类似于直接读取文本流所获得的详细访问级别;所以通过图书馆这样做似乎不太可能。

由于这是文字处理工作,您可以考虑将PDF转换为OpenOffice(使用 PDF导入扩展名),通过{{3}进行操作的可能性然后,从OpenOffice本身将其导出回PDF。

但要注意OOo python:文档很粗略,界面有时不稳定。访问“文本”可能不实用(更重要的是,因为文本只能逐行使用)。

另一种可能性(再次,不是对于胆小的人)是自己解码PDF。首先通过pdftk以未压缩格式获取它。这将产生一个标题,后跟一个

形式的对象流
INDEX R obj
<<
COMMANDS OR DATA
>>
[ stream 
STREAM OF TEXT
endstream ]
endobj

您可以阅读流和每个对象:

  1. 如果命令或数据仅为/Length 长度,则可能是文本流。其他GOTO 3。
  2. 解析对象(见下文)。如果长度发生变化,请记得正确更新/Length
  3. 注意当前输出文件的偏移量,将其保存在XREF [i](“第i个对象的参考偏移量”)中,并将其保存到输出文件中。
  4. 在对象的末尾,您将找到一个XREF对象,其中每个对象都以其所在的文件偏移量表示。这些偏移量(10位数字)必须根据您在XREF中保存的新偏移量进行重写。 对象的开头应进入PDF文件末尾的 startxref

    (要进行调试,首先要编写一个复制所有对象而不进行修改的例程。它必须重新计算外部参照和偏移量,并且仍然会产生与原始对象相同的PDF对象。)

    这样获得的PDF可以由pdftk重新压缩以节省空间。

    关于PDF文本对象解析,你基本上逐行检查文本输出命令(参见there be dragons 5.3.2)。大多数情况下,您将看到的命令为Tj

    9.95999 0 Td(Hello, world)Tj
    

    和变色命令(参见#4.5.1;最常用的是g和rg。)

    1 g             # Sets color to black (1 in colorspace Gray)
    1 0 0 rg        # Sets color to red (1,0,0 in colorspace RGB)
    

    然后,您将跟踪我们正在使用的任何颜色,例如,可以在您选择的几个Tj命令之间包含每个RG命令 - 一个设置文本颜色的命令,一个恢复原来的。通过这种方式,您可以确保图形状态不会“溢出”到任何附近的物体,线条等;它会增加对象Length并使得生成的PDF稍慢(但不是很多。你甚至可能都没注意到。)

答案 1 :(得分:0)

PDF structure非常复杂。另一种方法是导出文本,而不是只解析文本。

在每个页面上迭代并在其上使用extractText