105

我正在寻找有关如何使用 PDFMiner 和 Python 从 PDF 文件中提取文本的文档或示例。

看起来 PDFMiner 更新了他们的 API,我发现的所有相关示例都包含过时的代码(类和方法已更改)。我发现使从 PDF 文件中提取文本的任务更容易的库正在使用旧的 PDFMiner 语法,所以我不确定如何执行此操作。

事实上,我只是在查看源代码,看看我是否能弄清楚。

4

5 回答 5

203

这是使用当前版本的 PDFMiner(2016 年 9 月)从 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 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。我使用了pdfminer.six2018 年 11 月发布的 Python 库。

于 2014-10-21T19:47:47.837 回答
30

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
于 2017-06-10T18:34:33.540 回答
29

这适用于 2020 年 5 月,在 Python3 中使用 PDFminer 6。

安装包

$ pip install pdfminer.six

导入包

from pdfminer.high_level import extract_text

使用保存在磁盘上的 PDF

text = extract_text('report.pdf')

或者:

with open('report.pdf','rb') as f:
    text = extract_text(f)

使用内存中的 PDF

如果 PDF 已经在内存中,例如,如果使用 requests 库从 Web 检索,则可以使用该io库将其转换为流:

import io

response = requests.get(url)
text = extract_text(io.BytesIO(response.content))

与 PyPDF2 相比的性能和可靠性

PDFminer.six 比 PyPDF2(某些类型的 PDF 失败)更可靠,尤其是 PDF 版本 1.7

但是,使用 PDFminer.six 提取文本的速度明显比 PyPDF2 慢 6 倍。

我在 15" MBP (2018) 上计时了文本提取timeit,只计时了 10 页 PDF 的提取功能(无文件打开等),并得到了以下结果:

PDFminer.six: 2.88 sec
PyPDF2:       0.45 sec

pdfminer.six 占用空间也很大,需要 pycryptodome,它需要安装 GCC 和其他东西,将 Alpine Linux 上的最小安装 docker 映像从 80 MB 推到 350 MB。PyPDF2 没有明显的存储影响。

于 2020-05-17T19:07:23.490 回答
23

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

如今,根据您的需要,它有多个 api 从 PDF 中提取文本。在幕后,所有这些 api 都使用相同的逻辑来解析和分析布局。

(所有示例都假定您的 PDF 文件名为example.pdf

命令行

如果您只想提取一次文本,可以使用命令行工具 pdf2txt.py:

$ pdf2txt.py example.pdf

高级api

如果要使用 Python 提取文本(属性),可以使用高级 api。如果您想以编程方式从 PDF 中提取信息,这种方法是首选解决方案。

from pdfminer.high_level import extract_text

# Extract text from a pdf.
text = extract_text('example.pdf')

# Extract iterable of LTPage objects.
pages = extract_pages('example.pdf')

可组合的 API

还有一个可组合的 api,它在处理生成的对象时提供了很大的灵活性。例如,它允许您创建自己的布局算法。其他答案中建议使用此方法,但我只会在您需要自定义某些组件时推荐此方法。

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('example.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())

类似的问答在这里。我会尽量让它们保持同步。

于 2020-05-17T16:45:50.827 回答
0

此代码使用 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
于 2019-12-20T10:43:32.653 回答