我想列出 PDF 文件中存在的所有对象:文本块、图像、字体、页面对象,还有矢量形状(如果有)。
我希望通过 PyMuPDF 看到所有这些:
import fitz # pip install PyMuPDF
doc = fitz.open('test.pdf')
for xref in range(1, doc.xref_length()):
print(doc.xref_object(xref))
但是并非所有东西都在那里。例如,文本不存在。文本可以通过以下方式单独获取:
print(doc.load_page(0).get_text('dict'))
但我更寻找一种通用方法,而不是特定于文本元素的方法、用于其他对象的方法等。
问题:如何打印 PDF 文件中存在的所有对象?(文本块、图像、矢量形状等)
备注:
我已经阅读了How to extract text from a PDF file?和类似的问题,但这是特定于文本的,而我正在寻找所有对象/属性。
我已经阅读了如何打开 PDF raw?但这里没有帮助
使用文本编辑器打开 PDF 时,我们会看到很多人类无法阅读的二进制数据(似乎不仅仅是图像)。
TL;DR:我正在寻找类似的代表:
Object0
TYPE:TEXT
CONTENT:lorem ipsum
POSITION:123,123
Object1
TYPE:IMAGE
...
Object2
TYPE:...
...
请和我一起裸露。
这不是一个答案,但实际上是一个复杂的评论,以回应 OP 和评论者以及 PDF 规范本身对术语“对象”的过度使用。
PDF 对布尔值、整数、实数、字符串、名称、数组、字典、流和单例空对象具有一流的支持。但 PDF 不是将文档描述为一本巨大的字典,而是允许使用对象 ID 定义对象,并在以后通过对象 ID 引用它。这些称为间接对象。 PDF 文档实际上只是一个对象包,有一个索引和指向文件尾部“根”对象的指针。
PDF 中具有对象 ID 的这些对象是 PDF 中术语“对象”的非正式使用的典型含义。它们用于描述文档的结构以及生成文档所需的所有资源。然而这些对象不包含任何实际内容。
流用于保存由 PDF 查看器解释的小型基于后缀的命令语言。以下是来自 https://brendanzagaeski.appspot.com/0004.html 的示例,显示了 PDF 的实际有效片段,该片段显示了对象 ID 为 4 且类型为流的间接对象。右边是我的评论。
4 0 obj begin indirect object 4
<< /Length 55 >> { 'Length': 55}
stream begin stream type
BT begin-text-object command
/F1 18 Tf change-font to font with descriptor F1 at size 18pt
0 0 Td position-text at x=0, y=0
(Hello World) Tj render-text "Hello World"
ET end-text-object command
endstream end stream type
endobj end object
PDF 规范将流内的命令实例化的所有元素称为“图形对象”。是的,即使文本对象也是图形对象。然而,这些对象不是用属性声明的,它们是通过如何使用总体状态机构建它们的说明来定义的,如下所示。
因此,如果您希望所有图形对象都采用以下形式:
{ 'content': [
{ 'type': 'text', 'position': [0,0], 'text': "Hello World"
]}
您必须构建一个解释器来跟踪图形状态并存储解释器执行命令时创建的对象。基本的 PDF 查看器不必这样做,因为解释器紧密映射到图形 api 和图形层保存的图形状态。
您的意思是:
所有图像均来自 PDF 规范
https://opensource.adobe.com/dc-acrobat-sdk-docs/standards/pdfstandards/pdf/PDF32000_2008.pdf
您可以尝试使用 pdfplumber
import pdfplumber
with pdfplumber.open("path/to/file.pdf") as pdf:
first_page = pdf.pages[0]
print(first_page.objects)
阅读更多信息pdfplumber
from pdfminer.high_level import extract_pages
for page_layout in extract_pages("package-development.pdf"):
for element in page_layout:
print(element)
以下是输出的摘录:
<LTCurve 107.618,503.487,189.905,517.616>
<LTCurve 102.197,514.574,108.618,520.488>
<LTLine 742.906,690.178,1075.102,690.178>
<LTLine 185.379,36.023,1076.811,36.023>
<LTTextBoxHorizontal(0) 26.285,763.437,113.660,790.387 '" man/\n'>
<LTTextBoxHorizontal(1) 30.624,741.936,351.528,753.936 'The documentation will become the help pages in your package.\n'>
<LTTextBoxHorizontal(2) 29.272,711.703,329.175,726.553 '☑ Document each function with a roxygen block above its \n'>
<LTTextBoxHorizontal(3) 54.022,700.203,353.671,712.083 'definition. In RStudio, Code > Insert Roxygen Skeleton helps. \n'>
<LTTextBoxHorizontal(4) 29.272,674.803,351.319,689.653 '☑ Document each dataset with roxygen block above the name \n'>
<LTTextBoxHorizontal(5) 54.022,663.303,175.507,675.183 'of the dataset in quotes. \n'>
<LTTextBoxHorizontal(6) 29.272,637.903,299.154,652.753 '☑ Document the package with use_package_doc().\n'>
<LTTextBoxHorizontal(7) 384.050,765.279,450.186,779.279 'ROXYGEN2\n'>
<LTTextBoxHorizontal(8) 378.664,694.106,709.876,754.606 'The roxygen2 package lets you write documentation \ninline in your .R files with shorthand syntax. \n• Add roxygen documentation as comments beginning with #’. \n• Place a roxygen @ tag (right) after #’ to supply a specific section \n'>