我正在寻找有关如何使用PDFMiner和Python从PDF文件提取文本的文档或示例。
看来PDFMiner更新了它们的API,我发现的所有相关示例都包含过时的代码(类和方法已更改)。我发现的那些使从PDF文件提取文本的任务更容易的库正在使用旧的PDFMiner语法,因此我不确定如何执行此操作。
照原样,我只是在查看源代码,以查看是否可以解决。
我正在寻找有关如何使用PDFMiner和Python从PDF文件提取文本的文档或示例。
看来PDFMiner更新了它们的API,我发现的所有相关示例都包含过时的代码(类和方法已更改)。我发现的那些使从PDF文件提取文本的任务更容易的库正在使用旧的PDFMiner语法,因此我不确定如何执行此操作。
照原样,我只是在查看源代码,以查看是否可以解决。
PDFminer
不适用于Python 3.xx的原因,这可能是您收到import
错误的原因。pdfminer3k
如果是这样,您应该使用它,因为它是上述库的常规Python 3导入。
PDFminer
从GitHub上安装了它,并且可以很好地导入。您能否发布代码并发布完整的错误回溯?
Answers:
这是一个使用当前版本的PDFMiner从PDF文件提取文本的工作示例(2016年9月)
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 convert_pdf_to_txt(path):
rsrcmgr = PDFResourceManager()
retstr = StringIO()
codec = 'utf-8'
laparams = LAParams()
device = TextConverter(rsrcmgr, retstr, codec=codec, laparams=laparams)
fp = open(path, 'rb')
interpreter = PDFPageInterpreter(rsrcmgr, device)
password = ""
maxpages = 0
caching = True
pagenos=set()
for page in PDFPage.get_pages(fp, pagenos, maxpages=maxpages, password=password,caching=caching, check_extractable=True):
interpreter.process_page(page)
text = retstr.getvalue()
fp.close()
device.close()
retstr.close()
return text
PDFMiner的结构最近发生了变化,因此应该可以从PDF文件中提取文本。
编辑:截至2018年6月7日仍在工作。在Python版本3.x中验证
编辑:该解决方案于2019年10月3日与Python 3.7一起使用。我使用了Python库pdfminer.six
,该库于2018年11月发布。
import sys reload(sys) sys.setdefaultencoding('utf-8')
file(path, 'rb')
为`open(path,'rb')才能使我的工作。
DuckPuncher的出色回答,对于Python3,请确保您安装pdfminer2并执行以下操作:
import io
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.converter import TextConverter
from pdfminer.layout import LAParams
from pdfminer.pdfpage import PDFPage
def convert_pdf_to_txt(path):
rsrcmgr = PDFResourceManager()
retstr = io.StringIO()
codec = 'utf-8'
laparams = LAParams()
device = TextConverter(rsrcmgr, retstr, codec=codec, laparams=laparams)
fp = open(path, 'rb')
interpreter = PDFPageInterpreter(rsrcmgr, device)
password = ""
maxpages = 0
caching = True
pagenos = set()
for page in PDFPage.get_pages(fp, pagenos, maxpages=maxpages,
password=password,
caching=caching,
check_extractable=True):
interpreter.process_page(page)
fp.close()
device.close()
text = retstr.getvalue()
retstr.close()
return text
这项功能将于2020年5月在Python3中使用PDFminer 6实现。
$ pip install pdfminer.six
from pdfminer.high_level import extract_text
text = extract_text('report.pdf')
或者:
with open('report.pdf','rb') as f:
text = extract_text(open('report.pdf','rb'))
如果PDF已在内存中(例如,使用请求库从Web检索),则可以使用该io
库将其转换为流:
import io
response = requests.get(url)
text = extract_text(io.BytesIO(response.content))
PDFminer.six比PyPDF2(某些类型的PDF失败)更可靠地工作,尤其是PDF版本1.7
但是,使用PDFminer.six提取文本的速度比PyPDF2慢6倍。
我timeit
使用15英寸MBP(2018)来定时文本提取,仅用10页PDF来定时提取功能(没有打开文件等),并得到以下结果:
PDFminer.six: 2.88 sec
PyPDF2: 0.45 sec
pdfminer.six的占用空间也很大,需要pycryptodome,该pycryptodome需要安装GCC和其他工具,以将Alpine Linux上的最小安装docker映像从80 MB扩展到350 MB。PyPDF2没有明显的存储影响。
完全公开,我是pdfminer.six的维护者之一。
如今,有多种API可以根据您的需要从PDF中提取文本。在幕后,所有这些API都使用相同的逻辑来解析和分析布局。
命令行
如果您只想提取一次文本,则可以使用命令行工具pdf2txt.py:
$ pdf2txt.py example.pdf
高级API
如果要使用Python提取文本,则可以使用高级api。如果要以编程方式从许多PDF提取文本,则此方法是首选解决方案。
from pdfminer.high_level import extract_text
text = extract_text('samples/simple1.pdf')
可组合的API
还有一个可组合的api,它在处理结果对象方面具有很大的灵活性。例如,您可以使用它来实现自己的布局算法。其他答案中建议使用此方法,但仅在需要自定义pdfminer.six行为方式时,才建议使用此方法。
from io import StringIO
from pdfminer.converter import TextConverter
from pdfminer.layout import LAParams
from pdfminer.pdfdocument import PDFDocument
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.pdfpage import PDFPage
from pdfminer.pdfparser import PDFParser
output_string = StringIO()
with open('samples/simple1.pdf', 'rb') as in_file:
parser = PDFParser(in_file)
doc = PDFDocument(parser)
rsrcmgr = PDFResourceManager()
device = TextConverter(rsrcmgr, output_string, laparams=LAParams())
interpreter = PDFPageInterpreter(rsrcmgr, device)
for page in PDFPage.create_pages(doc):
interpreter.process_page(page)
print(output_string.getvalue())
此代码已通过pdfminer for python 3(pdfminer-20191125)进行了测试
from pdfminer.layout import LAParams
from pdfminer.converter import PDFPageAggregator
from pdfminer.pdfinterp import PDFResourceManager
from pdfminer.pdfinterp import PDFPageInterpreter
from pdfminer.pdfpage import PDFPage
from pdfminer.layout import LTTextBoxHorizontal
def parsedocument(document):
# convert all horizontal text into a lines list (one entry per line)
# document is a file stream
lines = []
rsrcmgr = PDFResourceManager()
laparams = LAParams()
device = PDFPageAggregator(rsrcmgr, laparams=laparams)
interpreter = PDFPageInterpreter(rsrcmgr, device)
for page in PDFPage.get_pages(document):
interpreter.process_page(page)
layout = device.get_result()
for element in layout:
if isinstance(element, LTTextBoxHorizontal):
lines.extend(element.get_text().splitlines())
return lines