PDFMiner – Iterando a través de páginas y convirtiéndolas en texto

Así que estoy tratando de sacar un poco de texto específico de algunos archivos PDF, y estoy usando Python con PDFMiner, pero tengo algunos problemas debido a los cambios en la API que ocurrieron en noviembre de 2013 . Básicamente, para obtener la parte del texto que quiero del PDF, actualmente tengo que convertir todo el archivo a texto y luego usar las funciones de cadena para obtener la parte que quiero. Lo que quiero hacer es recorrer cada página del PDF y convertir cada una de ellas en texto, una por una. Luego, una vez que haya encontrado la parte que quiero, simplemente evitaré que lea ese PDF.

Voy a publicar el código que se encuentra en mi editor de texto, pero no es la versión de trabajo, es más la versión de medio camino a la solución eficiente: P

#!/usr/bin/env python # -*- coding: utf-8 -*- from pdfminer.pdfparser import PDFParser from pdfminer.pdfdocument import PDFDocument from pdfminer.pdfpage import PDFPage from pdfminer.pdfinterp import PDFResourceManager from pdfminer.pdfinterp import PDFPageInterpreter from pdfminer.pdfdevice import PDFDevice from pdfminer.converter import LTChar, TextConverter from pdfminer.layout import LAParams from subprocess import call from cStringIO import StringIO import re import sys import os argNum = len(sys.argv) pdfLoc = str(sys.argv[1]) #CLI arguments def convert_pdf_to_txt(path): #converts pdf to raw text (not my function) 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 if (pdfLoc[-4:] == ".pdf"): contents = "" try: # Get the outlines (contents) of the document fp = open(pdfLoc, 'rb') #open a pdf document for reading parser = PDFParser(fp) document = PDFDocument(parser) outlines = document.get_outlines() for (level,title,dest,a,se) in outlines: title = re.sub(r".* \s", "", title) #get raw titles, stripped of formatting contents += title + "\n" except: #if pdfMiner can't get contents then manually get contents from text conversion #contents = convert_pdf_to_txt(pdfLoc) #startToCpos = contents.find("TABLE OF CONTENTS") #endToCpos = contents.rfind(". . .") #contents = contents[startToCpos:endToCpos+8] fp = open(pdfLoc, 'rb') #open a pdf document for reading parser = PDFParser(fp) document = PDFDocument(parser) pages = PDFPage(document, 3, {'Resources':'thing', 'MediaBox':'Thing'}) #God knows what's going on here for pageNumber, page in enumerate(pages.get_pages(PDFDocument, fp)): #The hell is the first argument? if pageNumber == 42: print "Hello" #for line in s: # print line # if (re.search("(\.\s){2,}", line) and not re.search("NOTES|SCOPE", line)): # line = re.sub("(\.\s){2,}", "", line) # line = re.sub("(\s?)*[0-9]*\n", "\n", line) # line = re.sub("^\s", "", line) # print line, #contents = contents.lower() #contents = re.sub("“", "\"", contents) #contents = re.sub("”", "\"", contents) #contents = re.sub("fi", "f", contents) #contents = re.sub(r"(TABLE OF CONTENTS|LIST OF TABLES|SCOPE|REFERENCED DOCUMENTS|Identification|System (o|O)verview|Document (o|O)verview|Title|Page|Table|Tab)(\n)?|\.\s?|Section|[0-9]", "", contents) #contents = re.sub(r"This document contains proprietary information and may not be reproduced in any form whatsoever, nor may be used by or its contents divulged to third\nparties without written permission from the ownerAll rights reservedNumber: STP SMEDate: -Jul-Issue: A of CMC STPNHIndustriesCLASSIFICATION\nNATO UNCLASSIFIED AGUSTAEUROCOPTEREUROCOPTER DEUTSCHLAND FOKKER", "", contents) #contents = re.sub(r"(\r?\n){2,}", "", contents) #contents = contents.lstrip() #contents = contents.rstrip() #print contents else: print "Not a valid PDF file" 

Esta es la forma antigua de hacerlo (o al menos una idea de cómo lo hizo la forma antigua, el hilo no me fue muy útil, por cierto). Pero ahora tengo que usar PDFPage.get_pages en lugar de PDFDocument.get_pages y los métodos y sus argumentos son completamente diferentes.

Actualmente, estoy tratando de averiguar qué diablos es la variable ‘Klass’ que paso al método get_pages de PDFPage .

Si alguien pudiera arrojar algo de luz sobre esta parte de la API o incluso proporcionar un ejemplo funcional, lo apreciaría muchísimo.

Trate de usar PyPDF2 . Es mucho más fácil de usar y no tan innecesariamente rico en funciones como PDFMiner (lo cual es bueno en su caso). Esto es lo que querías y es super simple de implementar.

 from PyPDF2 import PdfFileReader PDF = PdfFileReader(file(pdf_fp, 'rb')) if PDF.isEncrypted: decrypt = PDF.decrypt('') if decrypt == 0: print "Password Protected PDF: " + pdf_fp raise Exception("Nope") elif decrypt == 1 or decrypt == 2: print "Successfully Decrypted PDF" for page in PDF.pages: print page.extractText() '''page.extractText() is the unicode string of the contents of the page And I am assuming you know how to play with a string and use regex If you find what you want just break like so: if some_condition == True: break''' 

Tal vez llego un poco tarde y ya hayas resuelto esto, pero aún así, para futuras referencias:

Después de un poco de búsqueda recordé este enlace , desde el cual señalaría la siguiente parte (partes relevantes en negrita):

Python decidió hacer métodos de una manera que haga que la instancia a la que pertenece el método se pase automáticamente, pero no se reciba automáticamente: el primer parámetro de los métodos es la instancia a la que se llama el método. Eso hace que los métodos sean completamente iguales a las funciones, y deja que el nombre real se use para ti (aunque self es la convención, y la gente generalmente te frunce el ceño cuando usas otra cosa). Self no es especial para el código, es simplemente otro objeto