Wyodrębnij tekst z PDFów za pomocą PDFMinera w Pythonie

Zdobyj wiedzę na temat wyciągania tekstu z plików PDF w Pythonie

Page content

PDFMiner.six to potężna biblioteka Pythona do ekstrakcji tekstu, metadanych i informacji o układzie z dokumentów PDF. Ten przewodnik jest częścią naszego Narzędzi do Dokumentacji w 2026: Markdown, LaTeX, PDF i Przepływy Drukowania hubu.

W przeciwieństwie do prostych czytników PDF, oferuje głęboką analizę struktury PDF i skuteczne obsługuje złożone układy.

Ekstrakcja tekstu z pdf do markdown - wizualizacja IPAD

Co to jest PDFMiner i dlaczego go używać?

PDFMiner to biblioteka w pełni napisana w Pythonie, zaprojektowana do ekstrakcji i analizy tekstu z dokumentów PDF. Wersja .six to aktywnie utrzymana wersja rozgałęzienia, która obsługuje Python 3.x, podczas gdy oryginalny projekt PDFMiner nie jest już aktualizowany.

Główne cechy:

  • Implementacja w pełni w Pythonie (bez zależności zewnętrznych)
  • Szczegółowa analiza układu i pozycjonowanie tekstu
  • Wykrywanie czcionki i kodowania znaków
  • Obsługa zaszyfrowanych PDF
  • Wbudowane narzędzia wiersza poleceń
  • Rozszerzalna architektura do niestandardowego przetwarzania

PDFMiner jest szczególnie przydatny, gdy potrzebujesz precyzyjnego kontroli nad ekstrakcją tekstu, chcesz zachować informacje o układzie lub pracujesz z złożonymi dokumentami wielokolumnowymi. Choć może być wolniejszy niż niektóre alternatywy, jego dokładność i możliwości analizy szczegółowej sprawiają, że jest preferowanym wyborem dla przepływów pracy przetwarzania dokumentów. Dla odwrotnego przepływu pracy, możesz również być zainteresowany generowaniem PDF w Pythonie.

Instalacja i konfiguracja

Zainstaluj PDFMiner.six za pomocą pip:

pip install pdfminer.six

Dla środowisk wirtualnych (zalecane):

python -m venv venv
source venv/bin/activate  # Na Windows: venv\Scripts\activate
pip install pdfminer.six

Jeśli jesteś nowy w zarządzaniu pakietami Pythona, sprawdź nasz Szybki przewodnik po Pythonie dla dodatkowych informacji na temat pip i środowisk wirtualnych.

Sprawdź instalację:

pdf2txt.py --version

Biblioteka zawiera kilka narzędzi wiersza poleceń:

  • pdf2txt.py - Ekstrakcja tekstu z PDF
  • dumppdf.py - Wyświetlanie wewnętrznej struktury PDF
  • latin2ascii.py - Konwersja znaków łacińskich na ASCII

Te narzędzia uzupełniają inne narzędzia do manipulacji PDF takie jak Poppler, które oferują dodatkowe funkcje, takie jak ekstrakcja stron i konwersja formatów.

Podstawowa ekstrakcja tekstu

Prosta ekstrakcja tekstu

Najprostszy sposób ekstrakcji tekstu z PDF:

from pdfminer.high_level import extract_text

# Ekstraktuj cały tekst z PDF
text = extract_text('document.pdf')
print(text)

Ten wyższy poziom API obsługuje większość typowych przypadków użycia i zwraca cały dokument jako pojedynczy ciąg znaków.

Ekstrakcja tekstu z określonych stron

Aby ekstrahować tekst z określonych stron:

from pdfminer.high_level import extract_text

# Ekstraktuj tekst ze stron 2-5 (indeksowane od 0)
text = extract_text('document.pdf', page_numbers=[1, 2, 3, 4])
print(text)

To jest szczególnie przydatne w przypadku dużych dokumentów, gdzie potrzebujesz tylko określonych sekcji, znacznie poprawiając wydajność.

Ekstrakcja tekstu z iteracją po stronach

Dla przetwarzania stron indywidualnie:

from pdfminer.high_level import extract_pages
from pdfminer.layout import LTTextContainer

for page_layout in extract_pages('document.pdf'):
    for element in page_layout:
        if isinstance(element, LTTextContainer):
            print(element.get_text())

Ten podejście daje Ci większą kontrolę nad tym, jak każda strona jest przetwarzana, przydatne, gdy pracujesz z dokumentami, w których struktura stron się zmienia.

Zaawansowana analiza układu

Zrozumienie LAParams

LAParams (Parametry analizy układu) kontrolują, jak PDFMiner interpretuje układ dokumentu. Zrozumienie różnicy między PDFMiner a prostszymi bibliotekami jest tutaj kluczowe - PDFMiner faktycznie analizuje relacje przestrzenne między elementami tekstu.

from pdfminer.high_level import extract_text
from pdfminer.layout import LAParams

# Utwórz niestandardowe LAParams
laparams = LAParams(
    line_overlap=0.5,      # Minimalny nakładanie się linii tekstu
    char_margin=2.0,       # Margines znaków
    line_margin=0.5,       # Margines linii
    word_margin=0.1,       # Próg odstępu między słowami
    boxes_flow=0.5,        # Próg przepływu tekstowych pudełek
    detect_vertical=True,  # Wykrywanie tekstu pionowego
    all_texts=False        # Ekstrakcja tylko tekstu w pudełkach
)

text = extract_text('document.pdf', laparams=laparams)

Wyjaśnienie parametrów:

  • line_overlap: Ile linie muszą się nakładać pionowo, aby były uznane za tę samą linię (0.0-1.0)
  • char_margin: Maksymalny odstęp między znakami w tym samym słowie (w wielokrotności szerokości znaku)
  • line_margin: Maksymalny odstęp między liniami w tym samym akapicie
  • word_margin: Próg odstępu do oddzielania słów
  • boxes_flow: Próg przepływu kierunku tekstu w pudełkach
  • detect_vertical: Włącz wykrywanie tekstu pionowego (często spotykane w językach azjatyckich)

Ekstrakcja informacji o układzie

Pobierz szczegółowe informacje o pozycji i czcionce:

from pdfminer.high_level import extract_pages
from pdfminer.layout import LTTextBox, LTTextLine, LTChar

for page_layout in extract_pages('document.pdf'):
    for element in page_layout:
        if isinstance(element, LTTextBox):
            # Pobierz współrzędne pudełka
            x0, y0, x1, y1 = element.bbox
            print(f"Tekst w ({x0}, {y0}): {element.get_text()}")
            
            # Iteruj po liniach
            for text_line in element:
                if isinstance(text_line, LTTextLine):
                    # Pobierz szczegółowe informacje o znakach
                    for char in text_line:
                        if isinstance(char, LTChar):
                            print(f"Znak: {char.get_text()}, "
                                  f"Czcionka: {char.fontname}, "
                                  f"Rozmiar: {char.height}")

Taki poziom szczegółowości jest nieoceniony przy analizie dokumentów, ekstrakcji formularzy lub gdy potrzebujesz zrozumieć strukturę dokumentu programowo.

Obsługa różnych typów PDF

Zaszyfrowane PDF

PDFMiner potrafi obsługiwać PDF-y chronione hasłem:

from pdfminer.high_level import extract_text

# Ekstraktuj z zaszyfrowanego PDF
text = extract_text('encrypted.pdf', password='your_password')

Zauważ, że PDFMiner może ekstrahować tylko tekst z PDF-ów - nie może obejść ograniczeń bezpieczeństwa, które uniemożliwiają ekstrakcję tekstu na poziomie PDF.

Dokumenty wielokolumnowe

Dla dokumentów z wieloma kolumnami, dostosuj LAParams:

from pdfminer.high_level import extract_text
from pdfminer.layout import LAParams

# Optymalizacja dla układów wielokolumnowych
laparams = LAParams(
    detect_vertical=False,
    line_margin=0.3,
    word_margin=0.1,
    boxes_flow=0.3  # Niższa wartość dla lepszej detekcji kolumn
)

text = extract_text('multi_column.pdf', laparams=laparams)

Parametr boxes_flow jest szczególnie ważny dla dokumentów wielokolumnowych - niższe wartości pomagają PDFMinerowi wyróżnić oddzielne kolumny.

Tekst niemiecki i znaki Unicode

PDFMiner dobrze obsługuje Unicode, ale upewnij się, że kodowanie jest poprawne:

from pdfminer.high_level import extract_text

# Ekstraktuj tekst z obsługą Unicode
text = extract_text('multilingual.pdf', codec='utf-8')

# Zapisz do pliku z kodowaniem UTF-8
with open('output.txt', 'w', encoding='utf-8') as f:
    f.write(text)

Praca z zeskanowanymi PDF

PDFMiner nie potrafi bezpośrednio ekstrahować tekstu z zeskanowanych PDF (obrazów). Te wymagają OCR (Optyczne rozpoznawanie znaków). Jednak możesz połączyć PDFMiner z narzędziami OCR.

Oto jak wykryć, czy PDF jest zeskanowany i wymaga OCR:

from pdfminer.high_level import extract_text
from pdfminer.high_level import extract_pages
from pdfminer.layout import LTFigure, LTImage

def is_scanned_pdf(pdf_path):
    """Sprawdź, czy PDF wygląda na zeskanowany (przeważnie obrazy)"""
    text_count = 0
    image_count = 0
    
    for page_layout in extract_pages(pdf_path):
        for element in page_layout:
            if isinstance(element, (LTFigure, LTImage)):
                image_count += 1
            elif hasattr(element, 'get_text'):
                if element.get_text().strip():
                    text_count += 1
    
    # Jeśli przeważnie obrazy i mało tekstu, prawdopodobnie zeskanowany
    return image_count > text_count * 2

if is_scanned_pdf('document.pdf'):
    print("Ten PDF wygląda na zeskanowany - użyj OCR")
else:
    text = extract_text('document.pdf')
    print(text)

Dla zeskanowanych PDF, rozważ połączenie z Tesseract OCR lub użycie narzędzi do ekstrakcji obrazów z PDF najpierw, a następnie zastosowanie OCR do tych obrazów.

Użycie wiersza poleceń

PDFMiner zawiera potężne narzędzia wiersza poleceń:

Ekstrakcja tekstu za pomocą narzędzi wiersza poleceń

# Ekstraktuj tekst do stdout
pdf2txt.py document.pdf

# Zapisz do pliku
pdf2txt.py -o output.txt document.pdf

# Ekstraktuj konkretne strony
pdf2txt.py -p 1,2,3 document.pdf

# Ekstraktuj jako HTML
pdf2txt.py -t html -o output.html document.pdf

Zaawansowane opcje

# Niestandardowe parametry układu
pdf2txt.py -L 0.3 -W 0.1 document.pdf

# Ekstraktuj z szczegółowym układem (XML)
pdf2txt.py -t xml -o layout.xml document.pdf

# Ustaw hasło do zaszyfrowanego PDF
pdf2txt.py -P mypassword encrypted.pdf

Te narzędzia wiersza poleceń są doskonałe do szybkiego testowania, skryptów wiersza poleceń i integracji do automatyzowanych przepływów pracy.

Optymalizacja wydajności

Przetwarzanie dużych PDF

Dla dużych dokumentów, rozważ te strategie optymalizacji:

from pdfminer.high_level import extract_pages
from pdfminer.layout import LAParams

# Przetwarzaj tylko potrzebne strony
def extract_page_range(pdf_path, start_page, end_page):
    text_content = []
    for i, page_layout in enumerate(extract_pages(pdf_path)):
        if i < start_page:
            continue
        if i >= end_page:
            break
        text_content.append(page_layout)
    return text_content

# Wyłącz analizę układu dla prędkości
from pdfminer.high_level import extract_text
text = extract_text('large.pdf', laparams=None)  # znacznie szybsze

Przetwarzanie wsadowe

Dla efektywnego przetwarzania wielu PDF:

from multiprocessing import Pool
from pdfminer.high_level import extract_text
import os

def process_pdf(pdf_path):
    """Przetwórz pojedynczy plik PDF"""
    try:
        text = extract_text(pdf_path)
        output_path = pdf_path.replace('.pdf', '.txt')
        with open(output_path, 'w', encoding='utf-8') as f:
            f.write(text)
        return f"Przetworzono: {pdf_path}"
    except Exception as e:
        return f"Błąd przetwarzania {pdf_path}: {str(e)}"

# Przetwarzanie PDF w trybie równoległym
def batch_process_pdfs(pdf_directory, num_workers=4):
    pdf_files = [os.path.join(pdf_directory, f) 
                 for f in os.listdir(pdf_directory) 
                 if f.endswith('.pdf')]
    
    with Pool(num_workers) as pool:
        results = pool.map(process_pdf, pdf_files)
    
    for result in results:
        print(result)

# Użycie
batch_process_pdfs('/path/to/pdfs', num_workers=4)

Typowe problemy i rozwiązania

Problem: Nieprawidłowy porządek tekstu

Problem: Ekstrahowany tekst wygląda zamieszany lub jest w złym porządku.

Rozwiązanie: Dostosuj LAParams, szczególnie boxes_flow:

from pdfminer.layout import LAParams
laparams = LAParams(boxes_flow=0.3)  # Spróbuj różnych wartości
text = extract_text('document.pdf', laparams=laparams)

Problem: Brak spacji między słowami

Problem: Słowa są połączone bez spacji.

Rozwiązanie: Zwiększ word_margin:

laparams = LAParams(word_margin=0.2)  # Zwiększ od domyślnego 0.1
text = extract_text('document.pdf', laparams=laparams)

Problem: Błędy kodowania

Problem: Nieprawidłowe znaki lub błędy kodowania.

Rozwiązanie: Określ kodowanie jawnie:

text = extract_text('document.pdf', codec='utf-8')

Problem: Błędy pamięci z dużymi PDF

Problem: Błędy przepełnienia pamięci z dużych plików.

Rozwiązanie: Przetwarzaj stronę po stronie:

def extract_text_chunked(pdf_path, chunk_size=10):
    """Ekstraktuj tekst w fragmentach, aby zmniejszyć użycie pamięci"""
    all_text = []
    page_count = 0
    
    for page_layout in extract_pages(pdf_path):
        page_text = []
        for element in page_layout:
            if hasattr(element, 'get_text'):
                page_text.append(element.get_text())
        
        all_text.append(''.join(page_text))
        page_count += 1
        
        # Przetwarzaj w fragmentach
        if page_count % chunk_size == 0:
            yield ''.join(all_text)
            all_text = []
    
    # Wydaj pozostały tekst
    if all_text:
        yield ''.join(all_text)

Porównanie PDFMiner z alternatywami

Zrozumienie, kiedy używać PDFMiner w porównaniu do innych bibliotek jest ważne:

PDFMiner vs PyPDF2

PyPDF2 jest prostszy i szybszy, ale mniej dokładny:

  • Użyj PyPDF2 do: Prostych PDF, szybkiej ekstrakcji, łączenia i dzielenia PDF
  • Użyj PDFMiner do: Złożonych układów, dokładnego pozycjonowania tekstu, szczegółowej analizy

PDFMiner vs pdfplumber

pdfplumber opiera się na PDFMiner z wyższym poziomem API:

  • Użyj pdfplumber do: Ekstrakcji tabel, prostszego API, szybkiego prototypowania
  • Użyj PDFMiner do: Maksymalnej kontroli, niestandardowego przetwarzania, systemów produkcyjnych

PDFMiner vs PyMuPDF (fitz)

PyMuPDF jest znacznie szybszy, ale ma zależności w języku C:

  • Użyj PyMuPDF do: Aplikacji krytycznych pod względem wydajności, przetwarzania dużych ilości danych
  • Użyj PDFMiner do: Wymagań w języku Python, szczegółowej analizy układu

Praktyczny przykład: Ekstrakcja i analiza dokumentu

Oto kompletny przykład, który ekstrahuje tekst i dostarcza analizę dokumentu:

from pdfminer.high_level import extract_pages, extract_text
from pdfminer.layout import LTTextBox, LTChar
from collections import Counter
import re

def analyze_pdf(pdf_path):
    """Ekstraktuj tekst i dostarcz analizę dokumentu"""
    
    # Ekstraktuj pełny tekst
    full_text = extract_text(pdf_path)
    
    # Statystyki
    stats = {
        'total_chars': len(full_text),
        'total_words': len(full_text.split()),
        'total_lines': full_text.count('\n'),
        'fonts': Counter(),
        'font_sizes': Counter(),
        'pages': 0
    }
    
    # Szczegółowa analiza
    for page_layout in extract_pages(pdf_path):
        stats['pages'] += 1
        
        for element in page_layout:
            if isinstance(element, LTTextBox):
                for line in element:
                    for char in line:
                        if isinstance(char, LTChar):
                            stats['fonts'][char.fontname] += 1
                            stats['font_sizes'][round(char.height, 1)] += 1
    
    return {
        'text': full_text,
        'stats': stats,
        'most_common_font': stats['fonts'].most_common(1)[0] if stats['fonts'] else None,
        'most_common_size': stats['font_sizes'].most_common(1)[0] if stats['font_sizes'] else None
    }

# Użycie
result = analyze_pdf('document.pdf')
print(f"Strony: {result['stats']['pages']}")
print(f"Słowa: {result['stats']['total_words']}")
print(f"Główna czcionka: {result['most_common_font']}")
print(f"Główny rozmiar: {result['most_common_size']}")

Integracja z przepływami przetwarzania dokumentów

PDFMiner dobrze współpracuje w większych przepływach przetwarzania dokumentów. Na przykład, przy budowaniu systemów RAG (Retrieval-Augmented Generation) lub rozwiązań zarządzania dokumentami, możesz połączyć go z innymi narzędziami Pythona dla kompletnego przepływu.

Po ekstrakcji tekstu z PDF, często potrzebujesz konwersji do innych formatów. Możesz konwertować zawartość HTML na Markdown za pomocą bibliotek Pythona lub nawet wykorzystać konwersję z wykorzystaniem LLM z Ollama do inteligentnej transformacji dokumentów. Te techniki są szczególnie przydatne, gdy ekstrakcja z PDF generuje strukturalny tekst podobny do HTML, który wymaga czyszczenia i ponownego formatowania.

Dla kompletnych przepływów konwersji dokumentów, możesz również potrzebować obsługi konwersji dokumentów Word do Markdown, tworząc spójny przepływ pracy, który przetwarza wiele formatów dokumentów w wspólny format wyjściowy.

Najlepsze praktyki

  1. Zawsze używaj LAParams dla złożonych dokumentów - Ustawienia domyślne działają dla prostych dokumentów, ale dostosowanie LAParams znacząco poprawia wyniki dla złożonych układów.

  2. Testuj najpierw na przykładowych stronach - Przed przetwarzaniem dużych partii, przetestuj swoje ustawienia ekstrakcji na reprezentatywnych próbach.

  3. Obsłuż wyjątki łagodnie - Pliki PDF mogą być uszkodzone lub źle sformatowane. Zawsze otocz kod ekstrakcji blokami try-except.

  4. Kachuj ekstrahowany tekst - Dla wielokrotnego przetwarzania, kachuj ekstrahowany tekst, aby uniknąć ponownego przetwarzania.

  5. Weryfikuj jakość ekstrahowanego tekstu - Zaimplementuj sprawdzenia, aby zweryfikować jakość ekstrakcji (np. minimalna długość tekstu, oczekiwane słowa kluczowe).

  6. Rozważ alternatywy dla konkretnych przypadków użycia - Choć PDFMiner jest potężny, czasem specjalistyczne narzędzia (np. tabula-py do tabel) są bardziej odpowiednie.

  7. Zawsze aktualizuj PDFMiner - Wersja .six jest aktywnie utrzymana. Aktualizuj ją, aby uzyskać poprawki i ulepszenia.

  8. Dokumentuj swój kod odpowiednio - Gdy dzielisz skrypty ekstrakcji PDF, używaj odpowiednich bloków kodu w Markdown z podświetleniem składni dla lepszej czytelności.

Podsumowanie

PDFMiner.six to niezbędne narzędzie dla programistów Pythona pracujących z dokumentami PDF. Jego w pełni w Pythonie implementacja, szczegółowa analiza układu i rozszerzalna architektura sprawiają, że jest idealna do systemów przetwarzania dokumentów w środowisku produkcyjnym. Choć może mieć steeper learning curve niż prostsze biblioteki, precyzja i kontrola, które oferuje, są nie do pokonania dla złożonych zadań ekstrakcji PDF.

Czy jesteś budowaniem systemu zarządzania dokumentami, analizując artykuły naukowe, czy ekstrahując dane do przepływów danych maszynowego uczenia, PDFMiner dostarcza fundamentów dla niezawodnej ekstrakcji tekstu z PDF w Pythonie.

Powiązane zasoby

Powiązane artykuły na tym serwisie

Zewnętrzne odniesienia