如何使用 pdfminer 作为库

我试图从一个 pdf 文本数据使用 Pdfminer。我能够将这些数据提取到。使用 pdfminer 命令行工具 pdf2txt.py 成功地创建了 txt 文件。我目前这样做,然后使用一个 python 脚本来清除。Txt 文件。我想合并到脚本的 pdf 摘录过程,并节省自己的一个步骤。

当我发现这个链接时,我认为我找到了一些东西,但是我没有找到任何成功的解决方案。也许那里列出的函数需要再次更新,因为我正在使用一个新版本的 pdfminer。

我也尝试了这里显示的函数,但它也不能工作

我尝试的另一种方法是使用 os.system在脚本中调用该脚本。

我使用的是 Python 版本2.7.1和 pdfminer 版本20110227。

87553 次浏览

我知道回答自己的问题很没品味,但我想我可能已经想出来了,我不希望其他人浪费时间来解决我的问题。

我在问题中贴出的一个链接中采纳了这个建议,并重新使用了 pdf2txt.py 脚本中包含的当前脚本。下面是这个函数,如果它对其他人有用的话。感谢用户 skyl 发布了这个答案,我所需要做的就是做一些修改,让它能够与当前版本的 pdfminer 一起工作。

该函数接受一个 pdf 文件,并在同一目录中创建一个具有相同名称的. txt 文件。

def convert_pdf(path, outtype='txt', opts={}):
import sys
from pdfminer.pdfparser import PDFDocument, PDFParser
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter, process_pdf
from pdfminer.pdfdevice import PDFDevice, TagExtractor
from pdfminer.converter import XMLConverter, HTMLConverter, TextConverter
from pdfminer.cmapdb import CMapDB
from pdfminer.layout import LAParams
import getopt


outfile = path[:-3] + outtype
outdir = '/'.join(path.split('/')[:-1])


# debug option
debug = 0
# input option
password = ''
pagenos = set()
maxpages = 0
# output option
# ?outfile = None
# ?outtype = None
outdir = None
#layoutmode = 'normal'
codec = 'utf-8'
pageno = 1
scale = 1
showpageno = True
laparams = LAParams()
for (k, v) in opts:
if k == '-d': debug += 1
elif k == '-p': pagenos.update( int(x)-1 for x in v.split(',') )
elif k == '-m': maxpages = int(v)
elif k == '-P': password = v
elif k == '-o': outfile = v
elif k == '-n': laparams = None
elif k == '-A': laparams.all_texts = True
elif k == '-V': laparams.detect_vertical = True
elif k == '-M': laparams.char_margin = float(v)
elif k == '-L': laparams.line_margin = float(v)
elif k == '-W': laparams.word_margin = float(v)
elif k == '-F': laparams.boxes_flow = float(v)
elif k == '-Y': layoutmode = v
elif k == '-O': outdir = v
elif k == '-t': outtype = v
elif k == '-c': codec = v
elif k == '-s': scale = float(v)
#
#PDFDocument.debug = debug
#PDFParser.debug = debug
CMapDB.debug = debug
PDFResourceManager.debug = debug
PDFPageInterpreter.debug = debug
PDFDevice.debug = debug
#
rsrcmgr = PDFResourceManager()


outtype = 'text'


if outfile:
outfp = file(outfile, 'w')
else:
outfp = sys.stdout
device = TextConverter(rsrcmgr, outfp, codec=codec, laparams=laparams)




fp = file(path, 'rb')
process_pdf(rsrcmgr, device, fp, pagenos, maxpages=maxpages, password=password,
check_extractable=True)
fp.close()
device.close()
outfp.close()
return

这里是一个清理版本,我终于产生了适合我的工作。下面只是简单地返回给定文件名的 PDF 中的字符串。我希望这能节省一些人的时间。

from pdfminer.pdfinterp import PDFResourceManager, process_pdf
from pdfminer.converter import TextConverter
from pdfminer.layout import LAParams
from cStringIO import StringIO


def convert_pdf(path):


rsrcmgr = PDFResourceManager()
retstr = StringIO()
codec = 'utf-8'
laparams = LAParams()
device = TextConverter(rsrcmgr, retstr, codec=codec, laparams=laparams)


fp = file(path, 'rb')
process_pdf(rsrcmgr, device, fp)
fp.close()
device.close()


str = retstr.getvalue()
retstr.close()
return str

这个解决方案在 二零一三年十一月空气污染指数变动之前是有效的。

如果您使用的是通过 urllib2获取的数据,请尝试以下方法(已经开发并解释了 给你) :

def pdf_to_text(scraped_pdf_data):
from pdfminer.pdfinterp import PDFResourceManager, process_pdf
from pdfminer.pdfdevice import PDFDevice
from pdfminer.converter import TextConverter
from pdfminer.layout import LAParams


import StringIO
fp = StringIO.StringIO()
fp.write(scraped_pdf_data)
fp.seek(0)
outfp = StringIO.StringIO()


rsrcmgr = PDFResourceManager()
device = TextConverter(rsrcmgr, outfp, laparams=LAParams())
process_pdf(rsrcmgr, device, fp)
device.close()


t = outfp.getvalue()
outfp.close()
fp.close()
return t

与其他答案一样,这里的代码采用了 PDFMiner 本身提供的 pdf2txt 实用程序。因此,您也可以转换为 html 或 xml ——只需在上面的任何地方为 TextConverter分支 HTMLConverterXMLConverter即可。

这里是一个清理版本,我终于产生了适合我的工作。下面只是简单地返回给定文件名的 PDF 中的字符串。我希望这能节省一些人的时间。

from pdfminer.pdfinterp import PDFResourceManager, process_pdf
from pdfminer.converter import TextConverter
from pdfminer.layout import LAParams
from cStringIO import StringIO


def convert_pdf(path):


rsrcmgr = PDFResourceManager()
retstr = StringIO()
codec = 'utf-8'
laparams = LAParams()
device = TextConverter(rsrcmgr, retstr, codec=codec, laparams=laparams)


fp = file(path, 'rb')
process_pdf(rsrcmgr, device, fp)
fp.close()
device.close()


str = retstr.getvalue()
retstr.close()
return str

有没有人可以告诉我: 有没有一个特定的地方可以放置 pdf 文件?

这里有一个新的解决方案,可以与最新版本一起使用:

from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.converter import TextConverter
from pdfminer.layout import LAParams
from pdfminer.pdfpage import PDFPage
from cStringIO 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 = file(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()
str = retstr.getvalue()
retstr.close()
return str

以下对 non-process _ pdf 回答的修改直接从 URL 字符串名称中提取文本,并使用20140328和 Python 2.7版本:

from urllib2 import urlopen
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.converter import TextConverter
from pdfminer.layout import LAParams
from pdfminer.pdfpage import PDFPage
from cStringIO import StringIO
def convert_pdf_to_txt(url):
rsrcmgr = PDFResourceManager()
retstr = StringIO()
codec = 'utf-8'
laparams = LAParams()
device = TextConverter(rsrcmgr, retstr, codec=codec, laparams=laparams)


scrape = urlopen(url).read()
fp = StringIO(scrape)


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()
textstr = retstr.getvalue()
retstr.close()
return textstr

下面的代码适用于我最新版本的 PDFMiner,它采用 pdf 路径并返回文本。Txt 格式。

附注: 这是对上述答案的修改。

from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.converter import TextConverter
from pdfminer.layout import LAParams
from pdfminer.pdfpage import PDFPage
from cStringIO import StringIO


def convert_pdf_to_txt(path, outtype='txt'):
outfile = path[:-3] + outtype
rsrcmgr = PDFResourceManager()
codec = 'utf-8'
laparams = LAParams()
if outfile:
outfp = file(outfile, 'w')
else:
outfp = sys.stdout
device = TextConverter(rsrcmgr, outfp, codec=codec, laparams=laparams)
fp = file(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()
outfp.close()
return

如何使用 PDFMiner 从 PDF 打印 HTML:

import sys
import getopt
from Core.Interfaces.IReader import IReader
from pdfminer.pdfparser import PDFDocument, PDFParser
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter, process_pdf
from pdfminer.pdfdevice import PDFDevice, TagExtractor
from pdfminer.converter import XMLConverter, HTMLConverter, TextConverter
from pdfminer.cmapdb import CMapDB
from pdfminer.layout import LAParams
from cStringIO import StringIO


class PdfReader(object):
def __init__(self):
pass


def readText(self,path, outtype='text', opts={}):
outfile = path[:-3] + outtype
outdir = '/'.join(path.split('/')[:-1])
# debug option
debug = 0
# input option
password = ''
pagenos = set()
maxpages = 0
# output option
# ?outfile = None
# ?outtype = None
outdir = None
#layoutmode = 'normal'
codec = 'utf-8'
pageno = 1
scale = 1
showpageno = True
laparams = LAParams()
for (k, v) in opts:
if k == '-d': debug += 1
elif k == '-p': pagenos.update( int(x)-1 for x in v.split(',') )
elif k == '-m': maxpages = int(v)
elif k == '-P': password = v
elif k == '-o': outfile = v
elif k == '-n': laparams = None
elif k == '-A': laparams.all_texts = True
elif k == '-V': laparams.detect_vertical = True
elif k == '-M': laparams.char_margin = float(v)
elif k == '-L': laparams.line_margin = float(v)
elif k == '-W': laparams.word_margin = float(v)
elif k == '-F': laparams.boxes_flow = float(v)
elif k == '-Y': layoutmode = v
elif k == '-O': outdir = v
elif k == '-t': outtype = v
elif k == '-c': codec = v
elif k == '-s': scale = float(v)


print laparams
#
#PDFDocument.debug = debug
#PDFParser.debug = debug
CMapDB.debug = debug
PDFResourceManager.debug = debug
PDFPageInterpreter.debug = debug
PDFDevice.debug = debug
#
rsrcmgr = PDFResourceManager()


#outtype = 'text'


outfp = StringIO()


device = HTMLConverter(rsrcmgr, outfp, codec=codec, laparams=laparams)




fp = file(path, 'rb')
process_pdf(rsrcmgr, device, fp, pagenos, maxpages=maxpages, password=password,
check_extractable=True)
fp.close()
device.close()
print outfp.getvalue()
outfp.close()


return






reader = PdfReader()
opt = map(None,['-W','-L','-t'],[0.5,0.4,'html'])
reader.readText("/test_data/test.pdf","html",opt)

这对我来说是最新版本的 pdfminer (截至2014年9月) :

from pdfminer.pdfparser import PDFParser
from pdfminer.pdfdocument import PDFDocument
from pdfminer.pdfpage import PDFPage
from pdfminer.pdfpage import PDFTextExtractionNotAllowed
from pdfminer.pdfinterp import PDFResourceManager
from pdfminer.pdfinterp import PDFPageInterpreter
from pdfminer.pdfdevice import PDFDevice
from pdfminer.converter import TextConverter
from pdfminer.layout import LAParams
import unicodedata, codecs
from io import StringIO


def getPDFText(pdfFilenamePath):
retstr = StringIO()
parser = PDFParser(open(pdfFilenamePath,'r'))
try:
document = PDFDocument(parser)
except Exception as e:
print(pdfFilenamePath,'is not a readable pdf')
return ''
if document.is_extractable:
rsrcmgr = PDFResourceManager()
device = TextConverter(rsrcmgr,retstr, codec='ascii' , laparams = LAParams())
interpreter = PDFPageInterpreter(rsrcmgr, device)
for page in PDFPage.create_pages(document):
interpreter.process_page(page)
return retstr.getvalue()
else:
print(pdfFilenamePath,"Warning: could not extract text from pdf file.")
return ''


if __name__ == '__main__':
words = getPDFText(path)

以防有人还需要这个, 可以处理请求和 python 3.4。 感谢@bahmait 上面的回答:)

import requests


from io import StringIO
from pdfminer.pdfinterp import PDFResourceManager, process_pdf
from pdfminer.converter import TextConverter
from pdfminer.layout import LAParams




def pdf_to_text(url=None):
text = None
pdf = requests.get(url)


if pdf.ok:
fp = StringIO(str(pdf.content, 'utf-8'))
outfp = StringIO()


rsrcmgr = PDFResourceManager()
device = TextConverter(rsrcmgr, outfp, laparams=LAParams())
process_pdf(rsrcmgr, device, fp)
device.close()


text = outfp.getvalue()
outfp.close()
fp.close()
return text




if __name__ == "__main__":
hello_world_text = pdf_to_text("https://bytebucket.org/hsoft/pdfminer3k/raw/28edfc91caed830674ca0b928f42571f7dee6091/samples/simple1.pdf")
no_pdf = pdf_to_text('http://www.google.com/404')
print(hello_world_text)
print(no_pdf)

下面的代码片段能够使用 pdfminer 的最新版本(截至2016年3月23日)从 pdf 文档中提取纯文本。希望这个能帮上忙。

from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.converter import TextConverter
from pdfminer.layout import LAParams
from pdfminer.pdfpage import PDFPage
from cStringIO 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 = file(path, 'rb')


parser = PDFParser(fp)
doc = PDFDocument(parser)
parser.set_document(doc)


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()
print text
return text


convert_pdf_to_txt(<path_of_the_pdf_file>)

这是我的解决办法

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
import os


def convert_pdf_to_txt(path, pages=None):
if not pages:
pagenums = set()
else:
pagenums = set(pages)
output = StringIO()
manager = PDFResourceManager()
converter = TextConverter(manager, output, laparams=LAParams())
interpreter = PDFPageInterpreter(manager, converter)


infile = open(path, 'rb')
for page in PDFPage.get_pages(infile, pagenums):
interpreter.process_page(page)
infile.close()
converter.close()
text = output.getvalue()
output.close()
return text

例如,你只想阅读 pdf 文件的前3页:

text = convert_pdf_to_txt('../Data/EN-FINAL Table 9.pdf', pages=[0,1,2])

翻译: 奇芳

巨蟒: 3. x

这里有一个使用运行 python 3.6的 pdfminer.six的答案。它使用了 pdfminer.high_level模块,如果您只想从一个简单的 PDF 文件中获取原始文本,那么它可以抽象出许多底层细节。

import pdfminer
import io


def extract_raw_text(pdf_filename):
output = io.StringIO()
laparams = pdfminer.layout.LAParams() # Using the defaults seems to work fine


with open(pdf_filename, "rb") as pdffile:
pdfminer.high_level.extract_text_to_fp(pdffile, output, laparams=laparams)


return output.getvalue()

这个在蟒蛇3中为我工作。 它需要 PDFMiner.6包

pip install pdfminer.six

代码如下(与每个人的代码相同,只有一些小的修复) :

from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.converter import TextConverter
from pdfminer.layout import LAParams
from pdfminer.pdfpage import PDFPage
from six 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)
fp.close()
device.close()
str = retstr.getvalue()
retstr.close()


return str.replace("\\n","\n")

充分披露,我是 Pdf 6的维护者之一。它是 python3的 pdfminer 的社区维护版本。

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

(所有示例都假定 PDF 文件名为 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())