Szukam dokumentacji lub przykładów, jak wyodrębnić tekst z pliku PDF za pomocą PDFMiner z Pythonem.
Wygląda na to, że PDFMiner zaktualizował swoje API, a wszystkie odpowiednie przykłady, które znalazłem, zawierają przestarzały kod (klasy i metody uległy zmianie). Biblioteki, które znalazłem, które ułatwiają wyodrębnianie tekstu z pliku PDF, używają starej składni PDFMiner, więc nie jestem pewien, jak to zrobić.
W tej chwili patrzę tylko na kod źródłowy, aby zobaczyć, czy mogę to rozgryźć.
python
python-3.x
python-2.7
text-extraction
pdfminer
DuckPuncher
źródło
źródło
PDFminer
nie działa z Pythonem 3.xx To może być powód, dla którego otrzymujeszimport
błędy. Powinieneś użyćpdfminer3k
jeśli tak, ponieważ jest to stały import Pythona 3 wspomnianej biblioteki.PDFminer
z GitHub i importuje się dobrze. Czy możesz wysłać swój kod i zamieścić również pełne śledzenie błędów?Odpowiedzi:
Oto działający przykład wyodrębniania tekstu z pliku PDF przy użyciu aktualnej wersji PDFMiner (wrzesień 2016 r.)
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 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) text = retstr.getvalue() fp.close() device.close() retstr.close() return text
Struktura PDFMinera zmieniła się niedawno, więc powinno to działać w przypadku wyodrębniania tekstu z plików PDF.
Edycja : nadal działa od 7 czerwca 2018 r. Zweryfikowano w Pythonie w wersji 3.x
Edycja: Rozwiązanie działa z Pythonem 3.7 od 3 października 2019 r. Korzystałem z biblioteki Python
pdfminer.six
, wydanej w listopadzie 2018 r.źródło
import sys reload(sys) sys.setdefaultencoding('utf-8')
file(path, 'rb')
`open (path, 'rb'), aby mój działał.świetna odpowiedź od DuckPuncher, dla Python3 upewnij się, że zainstalowałeś pdfminer2 i wykonaj:
import io from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter from pdfminer.converter import TextConverter from pdfminer.layout import LAParams from pdfminer.pdfpage import PDFPage def convert_pdf_to_txt(path): rsrcmgr = PDFResourceManager() retstr = io.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() text = retstr.getvalue() retstr.close() return text
źródło
ImportError:
wiadomośćDziała to w maju 2020 roku przy użyciu PDFminer six w Python3.
Instalowanie pakietu
Importowanie pakietu
from pdfminer.high_level import extract_text
Korzystanie z pliku PDF zapisanego na dysku
text = extract_text('report.pdf')
Lub alternatywnie:
with open('report.pdf','rb') as f: text = extract_text(f)
Korzystanie z PDF już w pamięci
Jeśli plik PDF jest już w pamięci, na przykład jeśli został pobrany z Internetu za pomocą biblioteki żądań, można go przekonwertować na strumień za pomocą
io
biblioteki:import io response = requests.get(url) text = extract_text(io.BytesIO(response.content))
Wydajność i niezawodność w porównaniu z PyPDF2
PDFminer.six działa bardziej niezawodnie niż PyPDF2 (który nie działa w przypadku niektórych typów plików PDF), w szczególności PDF w wersji 1.7
Jednak ekstrakcja tekstu za pomocą PDFminer.six jest znacznie wolniejsza niż PyPDF2 o współczynnik 6.
Zsynchronizowałem wyodrębnianie tekstu z
timeit
15-calowym MBP (2018), synchronizując tylko funkcję ekstrakcji (bez otwierania pliku itp.) Z 10-stronicowym plikiem PDF i otrzymałem następujące wyniki:PDFminer.six: 2.88 sec PyPDF2: 0.45 sec
pdfminer.six ma również ogromne rozmiary, wymagając pycryptodome, który wymaga zainstalowania GCC i innych rzeczy, wypychając minimalny obraz dockera instalacyjnego w Alpine Linux z 80 MB do 350 MB. PyPDF2 nie ma zauważalnego wpływu na pamięć.
źródło
ImportError: cannot import name 'open_filename' from 'pdfminer.utils'
pojawia się błąd podczas uruchamianiafrom pdfminer.high_level import extract_text
Pełne ujawnienie, jestem jednym z opiekunów pdfminer.six.
Obecnie istnieje wiele interfejsów API do wyodrębniania tekstu z pliku PDF, w zależności od potrzeb. W tle wszystkie te interfejsy API używają tej samej logiki do analizowania i analizowania układu.
(We wszystkich przykładach przyjęto, że plik PDF nosi nazwę przykład.pdf )
Wiersz poleceń
Jeśli chcesz wyodrębnić tekst tylko raz, możesz użyć narzędzia wiersza poleceń pdf2txt.py:
Interfejs API wysokiego poziomu
Jeśli chcesz wyodrębnić tekst za pomocą Pythona, możesz użyć interfejsu API wysokiego poziomu. To podejście jest najlepszym rozwiązaniem, jeśli chcesz programowo wyodrębnić tekst z wielu plików PDF.
from pdfminer.high_level import extract_text text = extract_text('example.pdf')
Komponowalne API
Istnieje również komponowalny interfejs API, który zapewnia dużą elastyczność w obsłudze wynikowych obiektów. Na przykład możesz zaimplementować własny algorytm układu, używając tego. Ta metoda jest sugerowana w innych odpowiedziach, ale poleciłbym ją tylko wtedy, gdy musisz dostosować sposób zachowania pdfminer.six.
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())
źródło
ten kod jest testowany z pdfminer dla Pythona 3 (pdfminer-20191125)
from pdfminer.layout import LAParams from pdfminer.converter import PDFPageAggregator from pdfminer.pdfinterp import PDFResourceManager from pdfminer.pdfinterp import PDFPageInterpreter from pdfminer.pdfpage import PDFPage from pdfminer.layout import LTTextBoxHorizontal def parsedocument(document): # convert all horizontal text into a lines list (one entry per line) # document is a file stream lines = [] rsrcmgr = PDFResourceManager() laparams = LAParams() device = PDFPageAggregator(rsrcmgr, laparams=laparams) interpreter = PDFPageInterpreter(rsrcmgr, device) for page in PDFPage.get_pages(document): interpreter.process_page(page) layout = device.get_result() for element in layout: if isinstance(element, LTTextBoxHorizontal): lines.extend(element.get_text().splitlines()) return lines
źródło