我想使用 pypdf 遍历 pdf 页面中的所有对象。
我还想检查对象的类型是什么,是文本还是图形。
代码片段将是一个很大的帮助。
非常感谢
我认为 PyPDF 不是这项工作的正确工具。您需要解析页面本身(PyPDF 对其支持有限,请参阅API 文档),然后在更改某些对象后能够将结果保存在另一个 PDF 对象中。
您可以使用 解压缩 PDF pdftk
,这将允许您使用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
这可能会写成“序列”。它实际上由七个文本子对象组成,并且我所知道的没有库可以将流“解密”为其组件子对象,更不用说为它们分配适当的属性(在 PDF 中从图形状态下降,而在任何分层像 XML 这样的结构可能会与单个节点相关联,可能是通过继承)。
更多:流可能包括非文本命令(例如行)。然后改变“文本”的描边颜色实际上也会改变非文本对象的颜色。
库应该为您提供与直接读取文本流类似的详细访问级别;所以通过图书馆这样做似乎不太可能。
由于这是文字处理工作,您可能会考虑将 PDF 转换为 OpenOffice(使用PDF 导入扩展),通过OOo python对其进行操作,然后从 OpenOffice 本身将其导出回 PDF。
但是要小心,因为有龙:文档很粗略,界面有时不稳定。访问“文本”可能不切实际(更是如此,因为您只能逐行使用文本)。
另一种可能性(同样,不是胆小的人)是自己解码 PDF。首先通过pdftk
. 这将产生一个标题,后跟表单中的对象流
INDEX R obj
<<
COMMANDS OR DATA
>>
[ stream
STREAM OF TEXT
endstream ]
endobj
您可以读取流,并且对于每个对象:
/Length
长度,它可能是一个文本流。否则转到 3。/Length
适当更新。在对象的末尾,您会找到一个 XREF 对象,其中每个对象都用它所在的文件偏移量表示。这些偏移量(10 位数字)必须根据您保存在 XREF 中的新偏移量进行重写。此对象的开头应进入PDF 文件末尾的startxref 。
(要调试,首先编写一个复制所有对象而不进行修改的例程。它必须重新计算外部参照和偏移量,并且仍然产生与原始对象相同的 PDF 对象)。
这样获得的PDF可以重新压缩pdftk
以节省空间。
关于 PDF 文本对象解析,您基本上可以逐行检查以查找文本输出命令(参见PDF 参考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 变慢一点(但不是很慢。你甚至可能没有注意到)。
PDF结构非常复杂。如果您只想要文本,另一种方法是导出文本而不是解析它。
在每个页面上迭代并在其上使用extractText