我试图使用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文档中的文本?
在尝试textract(似乎有太多依赖项)和pypdf2(无法从我测试的pdf中提取文本)和tika(太慢)后,我最终使用xpdf中的pdftotext(正如已经在另一个答案中建议的那样),并直接从python中调用二进制(您可能需要调整路径到pdftotext):
import os, subprocess
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
args = ["/usr/local/bin/pdftotext",
'-enc',
'UTF-8',
"{}/my-pdf.pdf".format(SCRIPT_DIR),
'-']
res = subprocess.run(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
output = res.stdout.decode('utf-8')
有pdftotext,它基本上相同,但这假设pdftotext在/usr/local/bin中,而我在AWS lambda中使用这个,并希望从当前目录使用它。
顺便说一句:要在lambda上使用这个,你需要把二进制文件和依赖项放到libstdc++中。到函数中。我个人需要编译xpdf。由于这方面的说明会让这个答案变得更糟,我把它们放在了我的个人博客上。
从2021年开始,我想推荐pdfreader,因为pypddf2 /3现在看起来很麻烦,tika实际上是用java写的,需要在后台安装jre。Pdfreader是python的,目前维护得很好,这里有大量的文档。
正常安装: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)
你可以从这里下载tika-app-xxx.jar(最新)。
然后将这个.jar文件放在python脚本文件的同一文件夹中。
然后在脚本中插入如下代码:
import os
import os.path
tika_dir=os.path.join(os.path.dirname(__file__),'<tika-app-xxx>.jar')
def extract_pdf(source_pdf:str,target_txt:str):
os.system('java -jar '+tika_dir+' -t {} > {}'.format(source_pdf,target_txt))
该方法的优点:
更少的依赖。单个.jar文件比python包更容易管理。
开始支持。位置source_pdf可以是任何类型文档的目录。(.doc, .html, .odt等)
最新的。tika-app.jar始终先于相关版本的tika python包发布。
稳定。它比PyPDF更加稳定和维护良好(由Apache提供支持)。
劣势:
一个无头小丑是必要的。
我在这里找到了一个解决方案PDFLayoutTextStripper
这很好,因为它可以保持原始PDF的布局。
它是用Java编写的,但我已经添加了一个网关来支持Python。
示例代码:
from py4j.java_gateway import JavaGateway
gw = JavaGateway()
result = gw.entry_point.strip('samples/bus.pdf')
# result is a dict of {
# 'success': 'true' or 'false',
# 'payload': pdf file content if 'success' is 'true'
# 'error': error message if 'success' is 'false'
# }
print result['payload']
示例输出PDFLayoutTextStripper:
你可以在这里看到更多细节Stripper with Python