从加密的PDF中提取Python数据

问题描述 投票:6回答:1

我是纯数学的最新毕业生,只修过很少的基础编程课程。我正在实习,并且有一个内部数据分析项目。我必须分析最近几年的内部PDF。 PDF是“安全的”。换句话说,它们是加密的。但是,我们拥有所有这些文档,我们可以手动阅读它们。我们的目标是使用Python读取它们,因为这是我们有某种想法的语言。

[首先,我尝试使用一些Python库阅读PDF。但是,我发现的Python库无法读取加密的PDF。当时,我也无法使用Adobe Reader导出信息。

其次,我决定解密PDF。我成功使用了Python库pykepdf。 Pykepdf效果很好!但是,解密的PDF不能与之前的Python库(PyPDF2Tabula)一起读取。目前,我们已经进行了一些改进,因为使用Adobe Reader可以从解密的PDF中导出信息,但目标是使用Python进行所有操作。

我要显示的代码与未加密的PDF完美搭配,但不适用于加密的PDF。它也不适用于通过pykepdf获取的解密PDF。

我没有写代码。我在Python库PykepdfTabula的文档中找到它。我强烈推荐Al Sweigart在他的书“ 用Python自动完成无聊的东西”中编写PyPDF2解决方案。我还检查了代码是否工作正常,并具有我之前解释的限制。

第一个问题,如果程序使用从未加密过的文件,为什么我无法读取解密的文件?

第二个问题,我们可以用Python读取解密后的文件吗?哪个图书馆可以做到或不可能?是否可以提取所有解密的PDF?

感谢您的时间和帮助!

[我使用Python 3.7,Windows 10,Jupiter Notebook和Anaconda 2019.07发现了这些结果。

Python

import pikepdf
with pikepdf.open("encrypted.pdf") as pdf:
  num_pages = len(pdf.pages)
  del pdf.pages[-1]
  pdf.save("decrypted.pdf")

import tabula
tabula.read_pdf("decrypted.pdf", stream=True)

import PyPDF2
pdfFileObj=open("decrypted.pdf", "rb")
pdfReader=PyPDF2.PdfFileReader(pdfFileObj)
pdfReader.numPages
pageObj=pdfReader.getPage(0)
pageObj.extractText()

使用Tabula,我收到消息“输出文件为空。”

[使用PyPDF2,我只得到'/ n'

UPDATE 10/3/2019 Pdfminer.six(2018年11月版)

我使用DuckPuncher]发布的解决方案获得了更好的结果。对于解密的文件,我得到了标签,但没有数据。加密文件也会发生同样的情况。对于从未加密的文件,它非常完美。 由于我需要加密或解密文件的数据和标签,因此该代码对我不起作用。为了进行分析,我使用了Python的pdfminer.six该库于2018年11月发布。Pdfminer.six包含一个库pycryptodome。根据他们的文档,“ PyCryptodome是一个包含低级密码基元的自包含Python包。”

代码在堆栈交换问题中:Extracting text from a PDF file using PDFMiner in python?

[如果您想重复我的实验,我会很乐意。这是描述:

1)对从未加密的任何PDF运行此问题中提到的代码。

2)对PDF“安全”(这是Adobe使用的术语)执行相同的操作,我称其为加密的PDF。使用您可以在Google上找到的通用表格。下载后,您需要填写字段。否则,您将检查标签,而不是字段。数据在字段中。

3)使用Pykepdf解密加密的PDF。这将是解密的PDF。

4)使用解密的PDF重新运行代码。

UPDATE 10/4/2019 Camelot(版本2019年7月)

我找到了Python库Camelot。请注意,您需要camelot-py 0.7.3。

它非常强大,并且可与Python 3.7一起使用。另外,它非常易于使用。首先,您还需要安装Ghostscript

。否则,它将无法正常工作。您还需要安装Pandas请勿使用pip install camelot-py。而是使用pip install camelot-py [cv]]

该程序的作者是Vinayak Mehta。弗兰克·杜(Frank Du)在YouTube视频“使用Camelot使用Python从PDF提取表格数据”中分享了此代码。

我检查了代码,它正在处理未加密的文件。 但是,它不适用于加密和解密的文件,这是我的目标

Camelot旨在从PDF获取表。

这里是代码:

Python

import camelot
import pandas
name_table = camelot.read_pdf("uncrypted.pdf")
type(name_table)

#This is a Pandas dataframe
name_table[0]

first_table = name_table[0]   

#Translate camelot table object to a pandas dataframe
first_table.df

first_table.to_excel("unencrypted.xlsx")
#This creates an excel file.
#Same can be done with csv, json, html, or sqlite.

#To get all the tables of the pdf you need to use this code.
for table in name_table:
   print(table.df)

UPDATE 10/7/2019

我发现了一个窍门。如果使用Adobe Reader打开受保护的pdf,并使用Microsoft将其打印为PDF,然后将其另存为PDF,则可以使用该副本提取数据。我还可以将PDF文件转换为JSON,Excel,SQLite,CSV,HTML和其他格式。 这是我的问题的可能解决方案。但是,我仍在寻找一种没有该技巧的选项,因为目标是使用Python 100%做到这一点。我还担心,如果使用更好的加密方法,该技巧可能会失效。有时您需要多次使用Adobe Reader才能获取可提取的副本。

UPDATE 10/8/2019。第三个问题。

我现在有第三个问题。是否所有安全/加密的pdf均受密码保护?为什么pikepdf不起作用?我的猜测是,当前的pikepdf版本可以破坏某种类型的加密,但不能全部破解。@constt提到PyPDF2可以破坏某种类型的保护。但是,我对他说,我发现有一篇文章,PyPDF2可以破坏使用Adobe Acrobat Pro 6.0进行的加密,但不能破坏使用后版本的加密。

我是纯数学的最新毕业生,只修过很少的基础编程课程。我正在实习,并且有一个内部数据分析项目。我必须分析内部PDF ...

python pdf encryption extraction
1个回答
0
投票

我不确定我是否完全理解您的问题。可以完善下面的代码,但它可以读取加密的或未加密的PDF并提取文本。如果我误解了您的要求,请告诉我。

from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.converter import TextConverter
from pdfminer.layout import LAParams
from pdfminer.pdfpage import PDFPage
from io import StringIO

def extract_encrypted_pdf_text(path, encryption_true, decryption_password):

  output = StringIO()

  resource_manager = PDFResourceManager()
  laparams = LAParams()

  device = TextConverter(resource_manager, output, codec='utf-8', laparams=laparams)

  pdf_infile = open(path, 'rb')
  interpreter = PDFPageInterpreter(resource_manager, device)

  page_numbers = set()

  if encryption_true == False:
    for page in PDFPage.get_pages(pdf_infile, page_numbers, maxpages=0, caching=True, check_extractable=True):
      interpreter.process_page(page)

  elif encryption_true == True:
    for page in PDFPage.get_pages(pdf_infile, page_numbers, maxpages=0, password=decryption_password, caching=True, check_extractable=True):
      interpreter.process_page(page)

 text = output.getvalue()
 pdf_infile.close()
 device.close()
 output.close()
return text

results = extract_encrypted_pdf_text('encrypted.pdf', True, 'password')
print (results)
© www.soinside.com 2019 - 2024. All rights reserved.