如何在 Python 中解锁“安全”(读保护)PDF?

Posted

技术标签:

【中文标题】如何在 Python 中解锁“安全”(读保护)PDF?【英文标题】:How to unlock a "secured" (read-protected) PDF in Python? 【发布时间】:2015-03-27 09:29:51 【问题描述】:

在 Python 中,我使用 pdfminer 从 pdf 中读取文本,并使用此消息下方的代码。我现在收到一条错误消息:

File "/usr/local/lib/python2.7/dist-packages/pdfminer/pdfpage.py", line 124, in get_pages
    raise PDFTextExtractionNotAllowed('Text extraction is not allowed: %r' % fp)
PDFTextExtractionNotAllowed: Text extraction is not allowed: <cStringIO.StringO object at 0x7f79137a1
ab0>

当我用 Acrobat Pro 打开这个 pdf 文件时,发现它是安全的(或“读保护”)。但是,从this link 中,我了解到有许多服务可以轻松禁用这种读取保护(例如pdfunlock.com。当深入研究pdfminer 的源代码时,我看到上面的错误是在these lines 上生成的。

if check_extractable and not doc.is_extractable:
    raise PDFTextExtractionNotAllowed('Text extraction is not allowed: %r' % fp)

由于有许多服务可以在一秒钟内禁用这种读保护,我认为这很容易做到。看来.is_extractabledoc的一个简单属性,但我觉得不是把.is_extractable改成True那么简单..

有人知道如何使用 Python 禁用 pdf 的读取保护吗?欢迎所有提示!

================================================ =

您将在下面找到我目前用来从非读保护中提取文本的代码。

def getTextFromPDF(rawFile):
    resourceManager = PDFResourceManager(caching=True)
    outfp = StringIO()
    device = TextConverter(resourceManager, outfp, codec='utf-8', laparams=LAParams(), imagewriter=None)
    interpreter = PDFPageInterpreter(resourceManager, device)

    fileData = StringIO()
    fileData.write(rawFile)
    for page in PDFPage.get_pages(fileData, set(), maxpages=0, caching=True, check_extractable=True):
        interpreter.process_page(page)
    fileData.close()
    device.close()

    result = outfp.getvalue()

    outfp.close()
    return result

【问题讨论】:

您是否尝试将 .is_extractable 更改为 True?实际上,它很有可能会起作用。 您是否尝试过传递密码?对于 PDFPage.get_pages(fileData, set(), maxpages=0, password=password,caching=True, check_extractable=True) 中的页面: 见下面我的帖子。此行为在 pdfminer.six 中进行了更改,显示警告而不是引发错误。 【参考方案1】:

完全披露,我是pdfminer.six 的维护者之一。它是用于 python 3 的 pdfminer 的社区维护版本。

这个问题was fixed in 2020 默认禁用check_extractable。它现在显示警告而不是引发错误。

类似问答here。

【讨论】:

【参考方案2】:

我使用下面的代码使用pikepdf 并且能够覆盖。

import pikepdf

pdf = pikepdf.open('filepath', allow_overwriting_input=True)
pdf.save('filepath')

【讨论】:

【参考方案3】:

如果您想解锁文件夹中的所有pdf文件而不重命名它们,您可以使用此代码:

import glob, os, pikepdf

p = os.getcwd()
for file in glob.glob('*.pdf'):
   file_path = os.path.join(p, file).replace('\\','/')
   init_pdf = pikepdf.open(file_path)
   new_pdf = pikepdf.new()
   new_pdf.pages.extend(init_pdf.pages)
   new_pdf.save(str(file))

在pikepdf 库中,无法通过以相同名称保存现有文件来覆盖现有文件。相反,您想将页面复制到新创建的空 pdf 文件中,然后保存。

【讨论】:

这对我来说就像一个魅力。我只需要将密码参数添加到 init_pdf = pikepdf.open(file_path, password='mypass')【参考方案4】:

我也遇到了解析安全 pdf 的相同问题,但使用 pikepdf 库已解决。我在我的 jupyter notebbok 和 windows os 上尝试了这个库,但它给出了错误,但它在 Ubuntu 上运行顺利

【讨论】:

【参考方案5】:

“check_extractable=True”参数是设计使然。 一些 PDF 明确禁止提取文本,PDFMiner 遵循该指令。您可以覆盖它(提供 check_extractable=False),但风险自负。

【讨论】:

【参考方案6】:

我在尝试让 qpdf 在我的程序中运行时遇到了一些问题。我找到了一个有用的库 pikepdf,它基于 qpdf 并自动将 pdf 转换为可提取的。

使用它的代码非常简单:

import pikepdf

pdf = pikepdf.open('unextractable.pdf')
pdf.save('extractable.pdf')

【讨论】:

如果 pdf 受密码保护,则可以使用 pikepdf.open('unextractable.pdf', password='thepassword') 设置密码【参考方案7】:

在我的情况下,没有密码,但只需设置 check_extractable=False 即可绕过有问题文件的 PDFTextExtractionNotAllowed 异常(在其他查看器中打开正常)。

【讨论】:

文件未加密或密码保护时抛出错误时的最佳答案。 你能用例子分享一下吗【参考方案8】:

据我所知,在大多数情况下,PDF 的全部内容实际上是加密的,使用密码作为加密密钥,因此简单地将 .is_extractable 设置为 True 对您没有帮助。

根据这个帖子:

Does a library exist to remove passwords from PDFs programmatically?

我建议使用qpdf 之类的命令行工具删除读取保护(易于安装,例如在 Ubuntu 上,如果您还没有 apt-get install qpdf,请使用它):

qpdf --password=PASSWORD --decrypt SECURED.pdf UNSECURED.pdf

然后用pdfminer打开解锁的文件,然后做你的事情。

对于纯 Python 解决方案,您可以尝试使用 PyPDF2 及其 .decrypt() 方法,但它不适用于所有类型的加密,所以说真的,您最好只使用 qpdf -见:

https://github.com/mstamy2/PyPDF2/issues/53

【讨论】:

以上是关于如何在 Python 中解锁“安全”(读保护)PDF?的主要内容,如果未能解决你的问题,请参考以下文章

std::mutex 如何在不同的线程中解锁?

如何在 Roblox Studio 中解锁鼠标

如何在本机反应中解锁一个屏幕上的旋转

如何在 vSphere 6.x 中解锁并重置 SSO 密码

检查您是不是已在 Game Center/GameKit 中解锁成就

在 oracle 19c 中解锁 SCOTT 用户