J'essaie d'obtenir des données texte à partir d'un pdf en utilisant pdfminer . Je suis capable d'extraire ces données dans un fichier .txt avec succès avec l'outil de ligne de commande pdfminer pdf2txt.py. Je le fais actuellement, puis j'utilise un script python pour nettoyer le fichier .txt. Je voudrais incorporer le processus d'extraction de pdf dans le script et me sauver une étape.
Je pensais que j'étais sur quelque chose quand j'ai trouvé ce lien , mais je n'ai réussi avec aucune des solutions. Peut-être que la fonction qui y est répertoriée doit être mise à jour à nouveau car j'utilise une version plus récente de pdfminer.
J'ai également essayé la fonction présentée ici, mais elle n'a pas fonctionné non plus.
Une autre approche que j'ai essayée était d'appeler le script dans un script en utilisant os.system
. Cela a également échoué.
J'utilise Python version 2.7.1 et pdfminer version 20110227.
Voici une version nettoyée que j'ai finalement produite et qui a fonctionné pour moi. Ce qui suit renvoie simplement la chaîne dans un PDF, étant donné son nom de fichier. J'espère que cela fait gagner du temps à quelqu'un.
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
Cette solution était valable jusqu'au changements d'API en novembre 201 .
Voici une nouvelle solution qui fonctionne avec la dernière version:
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
Je sais que c'est un mauvais goût de répondre à votre propre question, mais je pense que j'ai peut-être compris cela et je ne veux pas que quelqu'un d'autre perde son temps à chercher une solution à mon problème.
J'ai suivi la suggestion dans l'un des liens publiés dans ma question et ré-proposé le script pdf2txt.py actuel inclus avec pdfminer. Voici la fonction au cas où elle serait utile à quelqu'un d'autre. Merci à l'utilisateur skyl d'avoir posté cette réponse, tout ce que j'avais à faire était de faire quelques changements pour le faire fonctionner avec la version actuelle de pdfminer.
Cette fonction prend un pdf et crée un fichier .txt dans le même répertoire avec le même nom.
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
Cela a fonctionné pour moi en utilisant la version la plus récente de pdfminer (en septembre 2014):
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 __== '__main__':
words = getPDFText(path)
Voici ma solution
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
Par exemple, vous voulez simplement lire les 3 premières pages d'un fichier pdf:
text = convert('../Data/EN-FINAL Table 9.pdf', pages=[0,1,2])
pdfminer.six == 20160614
python: 3.x
La modification suivante des réponses non-process_pdf extrait le texte directement d'un nom de chaîne URL et fonctionne avec la version 20140328 et 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
Le code suivant fonctionne pour moi avec la dernière version de PDFMiner, il prend le chemin du pdf et renvoie le texte au format .txt.
P.S: Il s'agit d'une modification de la réponse ci-dessus.
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
Si vous travaillez avec des données grattées via urllib2, essayez ceci (qui est développé et expliqué ici ):
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
Comme les autres réponses, le code ici adapte l'utilitaire pdf2txt que PDFMiner lui-même fournit. Vous pouvez donc également convertir en html ou xml - juste sous HTMLConverter
ou XMLConverter
pour TextConverter
partout ci-dessus.
juste au cas où quelqu'un en aurait encore besoin, le faire fonctionner avec les requêtes et python 3.4. merci à @bahmait pour sa réponse ci-dessus :)
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 __== "__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)
Voici une réponse qui fonctionne avec pdfminer.six
en cours d'exécution python 3.6. Il utilise le pdfminer.high_level
module qui résume une grande partie des détails sous-jacents si vous voulez simplement extraire le texte brut d'un simple fichier 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()
Voici une version nettoyée que j'ai finalement produite et qui a fonctionné pour moi. Ce qui suit renvoie simplement la chaîne dans un PDF, étant donné son nom de fichier. J'espère que cela fait gagner du temps à quelqu'un.
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
quelqu'un peut-il me dire: y a-t-il un endroit spécifique où le fichier pdf doit être placé ??
Celui-ci a fonctionné pour moi dans python 3. Il nécessite le package PDFMiner.six
pip install pdfminer.six
Le code est le suivant (même code que tout le monde, avec des corrections mineures):
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")
Seulement si quelqu'un en a encore besoin: Comment imprimer le HTML à partir d'un PDF en utilisant PDFMiner:
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)
Les extraits de code suivants sont capables d'extraire du texte brut à partir de documents pdf à l'aide de la dernière version de pdfminer (en date du 23 mars 2016). J'espère que cela t'aides.
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>)