在 Python 中读取 PDF 属性/元数据

Posted

技术标签:

【中文标题】在 Python 中读取 PDF 属性/元数据【英文标题】:Reading the PDF properties/metadata in Python 【发布时间】:2012-12-21 23:09:59 【问题描述】:

如何使用 Python 读取存储在 PDF 文件中的标题、作者、主题和关键字等属性/元数据?

【问题讨论】:

【参考方案1】:

试试pdfminer:

from pdfminer.pdfparser import PDFParser
from pdfminer.pdfdocument import PDFDocument

fp = open('diveintopython.pdf', 'rb')
parser = PDFParser(fp)
doc = PDFDocument(parser)

print(doc.info)  # The "Info" metadata

这是输出:

>>> ['CreationDate': 'D:20040520151901-0500',
  'Creator': 'DocBook XSL Stylesheets V1.52.2',
  'Keywords': 'Python, Dive Into Python, tutorial, object-oriented, programming, documentation, book, free',
  'Producer': 'htmldoc 1.8.23 Copyright 1997-2002 Easy Software Products, All Rights Reserved.',
  'Title': 'Dive Into Python']

有关更多信息,请查看本教程:A lightweight XMP parser for extracting PDF metadata in Python。

【讨论】:

提醒:pdfminer 的作者说它与 Python 3 不兼容,至少截至本文发布日期 (link) 截至 2013 年 11 月,“PDFDocument 类现在将 PDFParser 对象作为参数。删除了 PDFDocument.set_parser() 和 PDFParser.set_document()。”因此,您可以只执行 doc=PDFDocument(parser),并跳过对 set_document、set_parser 和初始化的调用。 @JSmyth PyPi Index 当前列出了三个与 Python 3 兼容的工作 pdfminer 分支。pip search pdfminer @zero2cx 感谢您的更新。我个人选择了pdfminer3k。很适合我的目的。必须阅读 repo 中的 API 文档,因为此处接受的答案不再是 pdfminer3k 的有效 API。 现在有一个正式的 Python 3 fork 项目github.com/pdfminer/pdfminer.six【参考方案2】:

对于 Python 3,请参阅 PyPDF2,并将来自 @Khaleel 的示例代码更新为:

from PyPDF2 import PdfFileReader
pdf_toread = PdfFileReader(open("test.pdf", "rb"))
pdf_info = pdf_toread.getDocumentInfo()
print(str(pdf_info))

使用pip install PyPDF2安装。

【讨论】:

我尝试了@Rabash 的答案,它给了我类似的结果。我认为这更好,因为它可以提供有关创建者的更好信息。此代码的创建者输出为“Microsoft...”,Rabash 的代码为我提供了一些编码字符。【参考方案3】:

对于 Python 3 和新的 pdfminer(pip install pdfminer3k):

import os
from pdfminer.pdfparser import PDFParser
from pdfminer.pdfparser import PDFDocument

fp = open("foo.pdf", 'rb')
parser = PDFParser(fp)
doc = PDFDocument(parser)
parser.set_document(doc)
doc.set_parser(parser)
if len(doc.info) > 0:
    info = doc.info[0]
    print(info)

【讨论】:

【参考方案4】:

Morten Zilmer 指出:pyPdf homepage 表示不再维护。

我已经使用pyPdf 实现了这一点。请参阅下面的示例代码。

from pyPdf import PdfFileReader
pdf_toread = PdfFileReader(open("doc2.pdf", "rb"))
pdf_info = pdf_toread.getDocumentInfo()
print(str(pdf_info))

输出:

'/Title': u'Microsoft Word - Agnico-Eagle - Complaint (00040197-2)', '/CreationDate': u"D:20111108111228-05'00'", '/Producer': u'Acrobat Distiller 10.0.0 (Windows)', '/ModDate': u"D:20111108112409-05'00'", '/Creator': u'PScript5.dll Version 5.2.2', '/Author': u'LdelPino'

【讨论】:

不要使用file,而是使用open 请注意,pyPdf 在主页上被标记为不再支持。【参考方案5】:

试试pdfreader 您可以访问文档目录元数据,如下所示:

   from pdfreader import PDFDocument    
   f = open("foo.pdf", 'rb')
   doc = PDFDocument(f)
   metadata = doc.root.Metadata

【讨论】:

谢谢!您能否详细说明为什么 PDF 库的 Python 市场需要另一种解决方案?它解决了哪些缺点?干杯! @CiprianTomoiagă 就我而言,目前最好的工具是 pdfminer,但它在大文档上速度很慢,而且并不总是适合解析文本数据。【参考方案6】:

pikepdf 提供了一种简单可靠的方法来执行此操作。

我用一堆 pdf 文件对此进行了测试,似乎有两种不同的方法可以在创建 PDF 时插入元数据。有些正在插入NUL 字节和其他乱码。 Pikepdf 处理得很好。

import pikepdf
p = pikepdf.Pdf.open(r'path/to/file.pdf')
str(p.docinfo['/Author'])  # mind the slash

这将返回一个字符串 - 如果您使用 str 包装它。例子:

'Normal person' 'ABC'

与其他选项比较:

pdfminer - 没有积极维护 pdfminer.six - 活跃 pdfreader - 激活(但仍建议您使用 easy_install, a.o.) pyPdf - 未维护 PyPDF2 - 未维护(Phaseit, Inc. 消失了)

Pdfminer.six:

pip install pdfminer.six

import pdfminer.pdfparser
import pdfminer.pdfdocument
h = open('path/to/file.pdf', 'rb')
p = pdfminer.pdfparser.PDFParser(h)
d = pdfminer.pdfparser.PDFDocument(p)
d.info[0]['Author']

这将返回一个二进制字符串,包括不可解码字符(如果存在)。例子:

b'Normal person' b'\xfe\xff\x00A\x00B\x00C' (ABC)

转换成字符串:

b'Normal person'.decode() 产生字符串 'Normal person' b'\xfe\xff\x00A\x00B\x00C'.decode(encoding='utf-8', errors='ignore').replace('\x00', '') 产生字符串 'ABC'

pdf阅读器

pip install pdfreader

import pdfreader
h = open(r'path/to/file.pdf', 'rb')
d = pdfreader.PDFDocument(h)
d.metadata['Author']

这将返回带有请求信息的字符串,或包含它找到的数据的十六进制表示的字符串。这也包括相同的不可解码字符。例子:

'Normal person' 'FEFF004100420043' (ABC)

然后,您首先需要检测这是否仍然是“编码的”,我认为这很麻烦。通过调用这段丑陋的代码,第二个可以成为一个合理的字符串:

s = 'FEFF004100420043'
''.join([c for c in (chr(int(s[i:i+2], 16)) for i in range(0, len(s), 2)) if c.isascii()]).replace('\x00', '')
>>> 'ABC'

【讨论】:

以上是关于在 Python 中读取 PDF 属性/元数据的主要内容,如果未能解决你的问题,请参考以下文章

从 nodeJS 读取 PDF 文档属性

从 ruby​​ 中的 pdf 文件中获取元数据

如何使用 Python 和 h5py 读取 HDF5 属性(元数据)

在 python 3.6 中提取 xlsx 工作簿文件元数据/属性

Postman、Python 以及将图像和元数据传递给 Web 服务

在笛卡尔积中,元数与元组个数是相同的意思吗