如何在Python 3.7中从PDF中提取文本

22

我正在使用Python从PDF文件中提取文本。 我的主要目标是创建一个程序,读取银行对账单并提取其文本以更新Excel文件,以便轻松记录每月支出。 目前,我只专注于从pdf文件中提取文本,但我不知道该如何做。

目前最好和最简单的从PDF文件中提取文本的方法是什么? 最好使用哪个库? 我应该如何实现?

我已经尝试使用PyPDF2,但每次使用extractText()从任何页面提取文本时都会返回空字符串。 我尝试安装textract,但由于我需要更多的库,所以出现了错误。

from PyPDF2 import PdfReader

reader = PdfReader("January2019.pdf")
page = reader.pages[0]
print(page.extract_text())

当它应该打印页面内容时,它会打印空字符串

编辑:此问题是针对非常旧的PyPDF2版本提出的。新版本的PyPDF2大大改善了文本提取功能


PDF文件是否具有文本内容? - Error - Syntactical Remorse
1
通过搜索 SO 上已经存在的问题如何? https://stackoverflow.com/questions/tagged/pypdf2 - lit
1
是的,PDF上确实有很多可以被我突出显示的实际文本。 - RaV1oLLi
@SyntaxVoid 支持 Monica,PyPDF2 的文本提取功能得到了很大的改进。现在相当不错。请试一试 :-) - Martin Thoma
另外,您从文档中提供的引用已不再适用(我是 PyPDF2 的维护者)。 - Martin Thoma
10个回答

52

我尝试了许多方法,包括PyPDF2和Tika,但都失败了。最终我找到了适合我的模块pdfplumber,你也可以试试。

希望对你有所帮助。

import pdfplumber
pdf = pdfplumber.open('pdffile.pdf')
page = pdf.pages[0]
text = page.extract_text()
print(text)
pdf.close()

你能否将此解决方案循环应用于多个文件夹和多个PDF,并将结果转换为数据框或类似的格式?如果您能看一下我的问题 -> https://stackoverflow.com/questions/66224627/how-to-extract-text-from-pdfs-in-folders-with-python-and-save-them-in-dataframe - AHK
非常好的包,比PyPDF2好多了,谢谢! - Aska

19

使用Tika对我很有帮助!

from tika import parser

rawText = parser.from_file('January2019.pdf')

rawList = rawText['content'].splitlines()

这使得从银行对账单中提取每一行并放进一个列表变得非常容易。


最终我找到了一个适合我的解决方案。所有其他的PDF扫描仪都不能满足我的使用情况,这可能是由于实际PDF的格式问题。然而,这个tika包完美地工作了。您需要安装最新版本的Java,以及Java tika server.jar文件。一旦您下载了java tika服务器jar文件,您可以在Windows上从cmd运行,java -jar java-tika-server.jar来运行本地服务器,然后这个包将适用于Python。 - dataviews
这是我找到的最好的东西,我尝试过PyPDF2pdfminer,但它适合我的需求,因为它可以逐行输出。 - Siddharth Das
我可以确认tika是非常好的选择。我喜欢它的简单性和从pdf中提取链接的能力。然而,对于我来说,我发现了更好的方法可以通过Windows命令行完成工作: “gswin64c -sDEVICE=txtwrite -o pdf2text.txt“sample.pdf”” ……只要您已经安装了gswin64c.exe并正确设置了路径。它已经安装在我的机器上,我只需要设置路径即可。 - Andrew Anderson

9
如果你正在寻找一个被维护且更大的项目,可以看看PyMuPDF。使用pip install pymupdf来安装它,并像这样使用它:
import fitz

def get_text(filepath: str) -> str:
    with fitz.open(filepath) as doc:
        text = ""
        for page in doc:
            text += page.getText().strip()
        return text

1
你拯救了我,让我免于失去理智。我正在尝试打开包含阿拉伯语、中文和其他非英语语言的PDF文件,而你的解决方案保留了这些字符,谢谢你。 - user1465073
该解决方案似乎比PyPDF2更有效。 - arjun

3

PyPDF2在从pdf中提取文本方面不太可靠,正如这里提到的一样。它说:

虽然PyPDF2有.extractText()方法,可以用于其页面对象(未在此示例中显示),但其效果并不好。有些PDF文件将返回文本,而有些则返回空字符串。当您想要从PDF中提取文本时,应该使用PDFMiner项目。PDFMiner更加稳健,专门设计用于从PDF中提取文本。

  1. 相反,您可以安装并使用pdfminer

    pip install pdfminer

  2. 或者你可以使用另一个名为pdftotext的开源实用程序,由xpdfreader提供。该页面上提供了使用该实用程序的说明。

您可以从这里下载命令行工具,并可以使用subprocess来使用pdftotext.exe实用程序。有关使用subprocess的详细说明,请参见此处


1

PyPDF2不能正确读取整个pdf文件。您必须使用此代码。

    import pdftotext

    pdfFileObj = open("January2019.pdf", 'rb')


    pdf = pdftotext.PDF(pdfFileObj)

    # Iterate over all the pages
    for page in pdf:
        print(page)

1
这里提供一种在Windows 10、Python 3.8下的替代解决方案。
示例测试PDF: https://drive.google.com/file/d/1aUfQAlvq5hA9kz2c9CyJADiY3KpY3-Vn/view?usp=sharing
#pip install pdfminer.six
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):
    '''Convert pdf content from a file path to text

    :path the file path
    '''
    rsrcmgr = PDFResourceManager()
    codec = 'utf-8'
    laparams = LAParams()

    with io.StringIO() as retstr:
        with TextConverter(rsrcmgr, retstr, codec=codec,
                           laparams=laparams) as device:
            with open(path, 'rb') as fp:
                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)

                return retstr.getvalue()


if __name__ == "__main__":
    print(convert_pdf_to_txt('C:\\Path\\To\\Test_PDF.pdf'))

0

我认为这段代码会正好符合你的需求:

import requests, time, datetime, os, threading, sys, configparser
import glob
import pdfplumber

for filename in glob.glob("*.pdf"):
    pdf = pdfplumber.open(filename)
    OutputFile = filename.replace('.pdf','.txt')
    fx2=open(OutputFile, "a+")
    for i in range(0,10000,1):
        try:
            page = pdf.pages[i]
            text = page.extract_text()
            print(text)
            fx2.write(text)
        except Exception as e: 
            print(e)
    fx2.close()
    pdf.close()

0
import pdftables_api
import os

c = pdftables_api.Client('MY-API-KEY')

file_path = "C:\\Users\\MyName\\Documents\\PDFTablesCode\\"

for file in os.listdir(file_path):
    if file.endswith(".pdf"):
        c.xlsx(os.path.join(file_path,file), file+'.xlsx')

请前往 https://pdftables.com 获取 API 密钥。

CSV,格式=csv

XML,格式=xml

HTML,格式=html

XLSX,格式=xlsx-single、格式=xlsx-multiple


0
尝试这个:
在终端中执行命令:pip install PyPDF2
import PyPDF2

reader = PyPDF2.PdfReader("mypdf.pdf")
for page in reader.pages:
    print(page.extract_text())

0

试试pdfreader。你可以提取纯文本或包含“pdf markdown”的解码文本:

from pdfreader import SimplePDFViewer, PageDoesNotExist

fd = open(you_pdf_file_name, "rb")
viewer = SimplePDFViewer(fd)

plain_text = ""
pdf_markdown = ""

try:
    while True:
        viewer.render()
        pdf_markdown += viewer.canvas.text_content
        plain_text += "".join(viewer.canvas.strings)
        viewer.next()
except PageDoesNotExist:
    pass


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接