如何将pdfminer用作库

74 投票
15 回答
90713 浏览
提问于 2025-04-16 16:05

我正在尝试使用 pdfminer 从一个PDF文件中提取文本数据。我已经成功地通过pdfminer的命令行工具pdf2txt.py将这些数据提取到一个.txt文件中。现在我先这样做,然后再用一个Python脚本来整理这个.txt文件。我想把提取PDF的过程直接放进脚本里,这样就可以省去一步。

我觉得我找到了一些有用的信息,当我看到这个链接时,但我尝试的解决方案都没有成功。也许那里列出的函数需要更新,因为我使用的是pdfminer的一个新版本。

我也尝试了这里展示的函数,但同样没有成功。

我尝试的另一种方法是通过 os.system 在一个脚本中调用另一个脚本。这也没有成功。

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

15 个回答

13

我知道自己回答自己的问题不太好,但我觉得我可能找到了答案,不想让其他人浪费时间去寻找解决办法。

我按照我问题中一个链接的建议,修改了pdfminer里自带的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
80

这里有一个适用于最新版本的新解决方案:

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
74

这是我最终整理出来的一个版本,对我来说有效。下面的代码只需要给定文件名,就能把字符串返回到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

这个解决方案在2013年11月之前是有效的,之后因为API的变化就不再适用了。

撰写回答