如何从PDF文件中提取文本?

357

我正在尝试使用Python提取PDF文件中包含的文本。

我正在使用PyPDF2包(版本1.27.2),并拥有以下脚本:

import PyPDF2

with open("sample.pdf", "rb") as pdf_file:
    read_pdf = PyPDF2.PdfFileReader(pdf_file)
    number_of_pages = read_pdf.getNumPages()
    page = read_pdf.pages[0]
    page_content = page.extractText()
print(page_content)

当我运行代码时,我的输出结果与PDF文档中的不同:

 ! " # $ % # $ % &% $ &' ( ) * % + , - % . / 0 1 ' * 2 3% 4
5
 ' % 1 $ # 2 6 % 3/ % 7 / ) ) / 8 % &) / 2 6 % 8 # 3" % 3" * % 31 3/ 9 # &)
%

我如何提取PDF文档中原样的文本?


8
请使用一个好的PDF查看器——如果可能的话,使用Adobe的标准Acrobat Reader复制文本。你得到了相同的结果吗?不同之处不在于文本,而是在于字体——字符代码映射到其他值。并非所有PDF都包含正确的数据来恢复这种情况。 - Jongware
我尝试了另一个文档,它可以工作。是的,看起来问题出在PDF本身。 - Simplicity
7
该PDF包含一个字符CMap表,因此在本线程中讨论的限制和解决方法是相关的 - https://dev59.com/VVHTa4cB1Zd3GeqPV_Tm. - dwarring
3
PDF文件中确实包含正确的CMAP,因此将临时字符映射转换为纯文本非常简单。但是,需要进行额外的处理才能检索到正确的文本顺序。Mac OS X的Quartz PDF渲染器是一个非常棘手的工具!在它最初的呈现顺序中,我收到了"m T’h iuss iisn ga tosam fopllloew DalFo dnogc wumithe ntht eI tutorial"。只有通过x坐标排序后,我才得到了一个更有可能正确的结果:"This is a sample PDF document I’m using to follow along with the tutorial"。 - Jongware
1
PyPDF2在单词之间/内添加随机空格,非常难以处理。 - YuMei
显示剩余4条评论
34个回答

10
在2020年,以上的解决方案对我所使用的特定pdf文件无效。以下是行之有效的方法。我使用的是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')) 

非常好的答案。还有一个Anaconda安装程序。我已经安装并提取了<5分钟的文本。[注意:Tika也可以工作,但pdfminer.six更快] - CreekGeek
你真是个救命恩人! - Sandeep
1
2023 年,用 3 行 pypdf 代码可以完成同样的任务:使用 pypdf 提取文本 - Martin Thoma

9
以下代码是使用Python 3编写的问题解决方案。在运行代码之前,请确保您已在环境中安装了pypdf库。如果未安装,请打开命令提示符并运行以下命令(而不是pip,您可能需要pip3):
pip install pypdf --upgrade

使用pypdf > 3.0.0的解决方案代码:

import pypdf

reader = PyPDF2.PdfReader('sample.pdf')
for page in reader.pages:
    print(page.extract_text())

6
如何将所有内容保存在一个文本文件中,并用于进一步的分析? - Rahul Agarwal

8

pdfplumber 是一个较好的库,用于读取和提取PDF文件中的数据。它还提供了读取表格数据的方法,在尝试了很多这样的库之后,pdfplumber 对我来说效果最好。

请注意,它最适合机器生成的PDF文件,而不是扫描得到的PDF文件。

import pdfplumber
with pdfplumber.open(r'D:\examplepdf.pdf') as pdf:
first_page = pdf.pages[0]
print(first_page.extract_text())

这很好,但我对输出格式有一个问题。我想将打印的结果保存到Pandas数据框中。这可能吗? - Serge de Gosson de Varennes

7

我有一个比OCR更好的解决方案,可以在从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

text= convert_pdf_to_txt('test.pdf')
print(text)

注意:最新版本不再使用codec参数。我通过删除它来解决了这个问题,即device = TextConverter(rsrcmgr, retstr, laparams=laparams) - Lee

6

使用以下代码,可以一次性提取多页pdf文本,而不是给出单个页面编号作为参数。

import PyPDF2
import collections
pdf_file = open('samples.pdf', 'rb')
read_pdf = PyPDF2.PdfFileReader(pdf_file)
number_of_pages = read_pdf.getNumPages()
c = collections.Counter(range(number_of_pages))
for i in c:
   page = read_pdf.getPage(i)
   page_content = page.extractText()
   print page_content.encode('utf-8')

这里唯一的问题是新页面的内容覆盖了上一个页面。 - Rahul Agarwal

5
截至2021年,我推荐使用pdfreader,因为PyPDF2 / 3现在似乎存在问题,而tika实际上是用java编写的,并需要后台运行jre。相比之下,pdfreader是基于Python的,目前维护良好,并且具有广泛的文档here
安装方式与平常一样:pip install pdfreader 使用的简短示例:
from pdfreader import PDFDocument, SimplePDFViewer

# get raw document
fd = open(file_name, "rb")
doc = PDFDocument(fd)

# there is an iterator for pages
page_one = next(doc.pages())
all_pages = [p for p in doc.pages()]

# and even a viewer
fd = open(file_name, "rb")
viewer = SimplePDFViewer(fd)

顺便提一下,在Windows上安装pdfreader需要在您的系统上安装Microsoft C++ Build Tools,而下面的答案建议直接使用pip安装pymupdf,无需任何额外要求。 - Raf
我无法在Jupyter Notebook上使用它,它一直导致内核崩溃。 - West

5

4
如果想要从表格中提取文本,我发现tabula易于实现、准确和快速:
要获取一个pandas数据框架:
import tabula

df = tabula.read_pdf('your.pdf')

df

默认情况下,它会忽略表格外的页面内容。到目前为止,我只在单页、单表文件上进行了测试,但是有些可选参数可以适应多页和/或多个表格。

安装方式:

pip install tabula-py
# or
conda install -c conda-forge tabula-py 

关于纯文本提取,请参见: https://dev59.com/51sW5IYBdhLWcg3wi32j#63190886


tabula很不错。在我测试的所有解决方案中,这是唯一能够保持行和字段顺序的解决方案。对于复杂的表格仍需要进行一些调整,但由于输出似乎可以从一个表格复制到另一个表格,并且存储在pandas.DataFrame中,因此很容易进行更正。 - Skippy le Grand Gourou
也要检查Camelot。 - Skippy le Grand Gourou

3

以下是提取文本的最简代码

代码:

# importing required modules
import PyPDF2

# creating a pdf file object
pdfFileObj = open('filename.pdf', 'rb')

# creating a pdf reader object
pdfReader = PyPDF2.PdfFileReader(pdfFileObj)

# printing number of pages in pdf file
print(pdfReader.numPages)

# creating a page object
pageObj = pdfReader.getPage(5)

# extracting text from page
print(pageObj.extractText())

# closing the pdf file object
pdfFileObj.close()

2
推荐使用“tika”。 - Vineesh TP
2
PyPDF2 / PyPDF3 / PyPDF4 都已经停止维护。请使用 pymupdf。pymupdf - Martin Thoma

2

您可以使用pytessaract和OpenCV轻松实现此操作。请参考以下代码。您可以从此文章中获取更多详细信息。

import os
from PIL import Image
from pdf2image import convert_from_path
import pytesseract

filePath = ‘021-DO-YOU-WONDER-ABOUT-RAIN-SNOW-SLEET-AND-HAIL-Free-Childrens-Book-By-Monkey-Pen.pdf’
doc = convert_from_path(filePath)

path, fileName = os.path.split(filePath)
fileBaseName, fileExtension = os.path.splitext(fileName)

for page_number, page_data in enumerate(doc):
txt = pytesseract.image_to_string(page_data).encode(“utf-8”)
print(“Page # {} — {}”.format(str(page_number),txt))

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