使用Python中的PDFMiner从PDF文件中提取文本?

Duc*_*her 71 python text-extraction pdfminer

Python版本2.7

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

看起来PDFMiner更新了他们的API,我发现的所有相关示例都包含过时的代码(类和方法已经改变).我发现的库使得从PDF文件中提取文本的任务更容易使用旧的PDFMiner语法,所以我不知道如何做到这一点.

事实上,我只是看源代码,看看能否解决它.

Duc*_*her 159

以下是使用当前版本的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
Run Code Online (Sandbox Code Playgroud)

PDFMiner的结构最近发生了变化,因此这应该适用于从PDF文件中提取文本.

编辑:截至2018年6月7日仍在工作.在Python版本3.x中验证

  • 工作正常,但是,我如何处理例如名称中的空格?假设我有一个包含4列的pdf,其中我在一个col中有first-和lastname,现在它用一行中的firstname和一行中的lastname解析,这里是一个例子http://docdro.id/rRyef3x (2认同)
  • 目前使用此代码导致导入错误:ImportError:没有名为'pdfminer.pdfpage'的模块 (2认同)
  • 感谢它在 python v2.7.12 和 ubuntu 16.04 上工作,尽管最好使用编码 utf-8 加载 pdf 文档,因为我的示例 pdf 有一些编码问题,所以在使用 utf-8 编码后尝试此操作,它解决了问题... `导入 sys reload(sys) sys.setdefaultencoding('utf-8')` (2认同)
  • 2017 年 7 月 19 日,仍在开发 Python v2.7.12。另外,值得注意的是,如果您想要 HTML 而不是纯文本,您可以将 `TextConverter` 切换为 `HTMLConverter`。 (2认同)
  • @DuckPuncher,它现在还在用吗?我不得不将`file(path,'rb')`更改为`open(path,'rb')以让我的工作. (2认同)
  • 仍然适用于 Python3.7 用户。安装了 pdfminer.6==20181108 包。迄今为止对于我的案例来说最好的解决方案,我比较了许多解决方案。 (2认同)
  • 查看以下答案,该答案在 2020 年 5 月有效,非常简单: `from pdfminer.high_level import extract_text` 然后 `text = extract_text('report.pdf')` /sf/answers/4330011101/ (2认同)
  • 我收到“意外关键字参数‘编解码器’”错误。似乎“编解码器”参数已被删除。当我从 TextConverter(...) 中删除编解码器参数时它起作用了 (2认同)

jua*_*aza 26

来自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)

    text = retstr.getvalue()

    fp.close()
    device.close()
    retstr.close()
    return text
Run Code Online (Sandbox Code Playgroud)

  • 谢谢我最终得到了它,我从conda forge安装了pdfminer.six (5认同)
  • 对于Python 3,pdfminer.six是推荐的软件包 - https://github.com/pdfminer/pdfminer.six (5认同)
  • 它对我不起作用:ModuleNotFoundError:没有名为“pdfminer.pdfpage”的模块我正在使用 python 3.6 (2认同)

Cor*_*mer 24

这在 2020 年 5 月使用 Python3 中的 PDFminer 6 起作用。

安装包

$ pip install pdfminer.six
Run Code Online (Sandbox Code Playgroud)

导入包

from pdfminer.high_level import extract_text
Run Code Online (Sandbox Code Playgroud)

使用保存在磁盘上的 PDF

text = extract_text('report.pdf')
Run Code Online (Sandbox Code Playgroud)

或者:

with open('report.pdf','rb') as f:
    text = extract_text(f)
Run Code Online (Sandbox Code Playgroud)

使用内存中已有的 PDF

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

import io

response = requests.get(url)
text = extract_text(io.BytesIO(response.content))
Run Code Online (Sandbox Code Playgroud)

与 PyPDF2 相比的性能和可靠性

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
Run Code Online (Sandbox Code Playgroud)

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

  • 自从给出这个答案以来,PyPDF2 有很多改进。尤其是文本提取得到了很大的改进。在[我的基准测试](https://github.com/py-pdf/benchmarks)中,PyPDF2 的文本提取现在比 pdfminer 的文本提取更好 (2认同)

Pie*_*ter 18

完全公开,我是pdfminer.six的维护者之一。

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

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

命令行

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

$ pdf2txt.py example.pdf
Run Code Online (Sandbox Code Playgroud)

高级api

如果要使用 Python 提取文本,可以使用高级 api。如果您想以编程方式从许多 PDF 中提取文本,则此方法是首选解决方案。

from pdfminer.high_level import extract_text

text = extract_text('example.pdf')
Run Code Online (Sandbox Code Playgroud)

可组合的 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('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())
Run Code Online (Sandbox Code Playgroud)