2013-06-13 4 views
8

Problema
Sto provando a determinare di che tipo è un documento (ad esempio supplica, corrispondenza, citazione, ecc.) Cercando nel suo testo, preferibilmente usando python. Tutti i PDF sono ricercabili, ma non ho trovato una soluzione per analizzarli con python e applicare uno script per cercarlo (non lo converti prima in un file di testo, ma potrebbe essere molto dispendioso per n documenti).Ricerca di testo in un PDF usando Python?

Quello che ho fatto finora
Ho guardato in pypdf, pdfminer, adobe pdf la documentazione, e tutte le domande qui sono riuscito a trovare (anche se nessuno sembrava di risolvere direttamente il problema). PDFminer sembra avere il maggior potenziale, ma dopo aver letto la documentazione non sono nemmeno sicuro da dove cominciare.

Esiste un metodo semplice ed efficace per leggere il testo PDF, per pagina, riga o per l'intero documento? O altri metodi alternativi?

+0

Stavo cercando la stessa soluzione. Il problema è che i documenti PDF sono noti per suddividere il testo in blocchi difficili da ricomporre. Dipende dal programma che ha scritto il PDF. Ho finito per usare PDFminer e un sacco di codice "elif" per analizzare i PDF. –

+1

Solo un pensiero, forse non pratico ... Se sei alla disperata ricerca di una soluzione alternativa, puoi provare a chiamare pdfgrep (http://pdfgrep.sourceforge.net/) per effettuare la ricerca. –

risposta

17

Questo si chiama PDF raschiatura, ed è molto difficile perché:

  • PDF è un formato di documento progettato per essere stampato, non deve essere analizzato. All'interno di un documento PDF, il testo non è in ordine particolare (a meno che l'ordine sia importante per la stampa), la maggior parte delle volte la struttura di testo originale viene persa (le lettere non possono essere raggruppate in quanto le parole e le parole non possono essere raggruppate in frasi, e l'ordine in cui sono inseriti in la carta è spesso casuale).
  • Ci sono tonnellate di software che generano PDF, molti sono difettosi.

Strumenti come PDFminer utilizzano l'euristica per raggruppare nuovamente lettere e parole in base alla loro posizione nella pagina. Sono d'accordo, l'interfaccia è di livello piuttosto basso, ma ha più senso quando si conosce quale problema stanno cercando di risolvere (alla fine, ciò che conta è scegliere quanto vicino deve essere una lettera/parola/linea vicina ai vicini per essere considerato parte di un paragrafo).

Un'alternativa dispendiosa (in termini di tempo/potenza del computer) genera immagini per ogni pagina e le alimenta all'OCR, potrebbe valere la pena provare se si dispone di un ottimo OCR.

Quindi la mia risposta è no, non esiste un metodo semplice ed efficace per estrarre il testo da file PDF - se i documenti hanno una struttura nota, è possibile perfezionare le regole e ottenere buoni risultati, ma è sempre un gioco d'azzardo.

Mi piacerebbe davvero essere smentito.

+0

Tutti i documenti sono stati scansionati in pdf e OCR è diventato ricercabile - è diverso da quello che stai descrivendo? – Insarov

+0

@Insarov: esattamente quello di cui sto parlando, ogni OCR che vale lo stipendio avrà la possibilità di generare un file di testo puro insieme al file PDF. –

3

Sono d'accordo con @Paulo Il data mining in PDF è un enorme dolore. Ma si potrebbe avere successo con pdftotext che fa parte della suite Xpdf liberamente disponibile qui:

http://www.foolabs.com/xpdf/download.html

Questo dovrebbe essere sufficiente per il vostro scopo, se siete solo in cerca di singole parole chiave.

pdftotext è un'utilità della riga di comando, ma molto semplice da utilizzare. Ti darà file di testo, che potresti trovare più facile da usare.

6

Ho scritto sistemi estesi per l'azienda per cui lavoro per convertire i PDF in dati per l'elaborazione (fatture, pagamenti, biglietti scansionati, ecc.) e @Paulo Scardine è corretto - non esiste un modo completamente affidabile e semplice per farlo. Detto questo, il modo più veloce, più affidabile e meno intensivo è utilizzare pdftotext, parte del set di strumenti xpdf. Questo strumento convertirà rapidamente i PDF ricercabili in un file di testo, che potrai leggere e analizzare con Python. Suggerimento: utilizzare l'argomento -layout. E a proposito, non tutti i PDF sono ricercabili, solo quelli che contengono testo. Alcuni PDF contengono solo immagini senza testo.

+0

perché è il modo più veloce e affidabile? Qualche prova? –

+1

Se c'è un modo per convertire un PDF in un file di testo, c'è un modo per farlo senza scrivere un nuovo file? Qualcosa come leggere un documento in memoria? (Almeno, in un modo così semplice come convertirlo?). – Insarov

+0

@Insarov, io non la penso così, non con pdftotext. Ma potrei sbagliarmi, dovrai controllare i documenti. Puoi farlo con pyPdf e pdfminer, ma sono molto più lenti di pdftotext, anche con pdftotext che scrive sul file. – MikeHunter

2

Recentemente ho iniziato a usare ScraperWiki per fare ciò che hai descritto.

Ecco uno example di utilizzo di ScraperWiki per estrarre i dati PDF.

La funzione scraperwiki.pdftoxml() restituisce una struttura XML.

È quindi possibile utilizzare BeautifulSoup per analizzarlo in un albero navigabile.

Ecco il mio codice per -

import scraperwiki, urllib2 
from bs4 import BeautifulSoup 

def send_Request(url): 
#Get content, regardless of whether an HTML, XML or PDF file 
    pageContent = urllib2.urlopen(url) 
    return pageContent 

def process_PDF(fileLocation): 
#Use this to get PDF, covert to XML 
    pdfToProcess = send_Request(fileLocation) 
    pdfToObject = scraperwiki.pdftoxml(pdfToProcess.read()) 
    return pdfToObject 

def parse_HTML_tree(contentToParse): 
#returns a navigatibale tree, which you can iterate through 
    soup = BeautifulSoup(contentToParse) 
    return soup 

pdf = process_PDF('http://greenteapress.com/thinkstats/thinkstats.pdf') 
pdfToSoup = parse_HTML_tree(pdf) 
soupToArray = pdfToSoup.findAll('text') 
for line in soupToArray: 
    print line 

questo codice sta per stampare un intero, grande brutta mucchio di <text> tag. Ogni pagina è separata con un </page>, se questa è una qualsiasi consolazione.

Se si desidera che il contenuto all'interno dei <text> tag, che potrebbero includere intestazioni avvolto in <b> per esempio, utilizzare line.contents

Se desideri solo ogni riga di testo, che non includono i tag, utilizzare line.getText()

E ' disordinato e doloroso, ma funzionerà con documenti PDF ricercabili. Finora ho trovato questo per essere accurato, ma doloroso.

+1

Ho provato ad usare scraperwiki, sto ottenendo Il sistema non riesce a trovare il percorso specificato errore. @JasTonAChair qualsiasi aiuto apprezzato. – user1211

+0

@JasTonAChair Am errore ottenere: - BeautifulSoup ([il tuo markup]) a questo: BeautifulSoup ([il tuo markup], "lxml") – venkat

0

Ecco la soluzione che ho trovato comodo per questo problema. Nella variabile di testo ottieni il testo da PDF per cercare in esso. Ma ho conservato anche l'idea di spiting il testo in parole chiave come ho trovato su questo sito: https://medium.com/@rqaiserr/how-to-convert-pdfs-into-searchable-key-words-with-python-85aab86c544f da fossi preso questa soluzione, anche se facendo NLTK non era molto semplice, potrebbe essere utile per ulteriori scopi:

import PyPDF2 
import textract 

from nltk.tokenize import word_tokenize 
from nltk.corpus import stopwords 

def searchInPDF(filename, key): 
    occurrences = 0 
    pdfFileObj = open(filename,'rb') 
    pdfReader = PyPDF2.PdfFileReader(pdfFileObj) 
    num_pages = pdfReader.numPages 
    count = 0 
    text = "" 
    while count < num_pages: 
     pageObj = pdfReader.getPage(count) 
     count +=1 
     text += pageObj.extractText() 
    if text != "": 
     text = text 
    else: 
     text = textract.process(filename, method='tesseract', language='eng') 
    tokens = word_tokenize(text) 
    punctuation = ['(',')',';',':','[',']',','] 
    stop_words = stopwords.words('english') 
    keywords = [word for word in tokens if not word in stop_words and not word in punctuation] 
    for k in keywords: 
     if key == k: occurrences+=1 
    return occurrences 

pdf_filename = '/home/florin/Downloads/python.pdf' 
search_for = 'string' 
print searchInPDF (pdf_filename,search_for)