PDF-Parsing klingt einfach, bis du es versucht hast. Eine PDF-Datei sieht für Menschen verständlich aus, aber intern ist es ein Chaos aus Content-Streams, Rendering-Operationen und Kodierungen. Die falsche Library wählen? Dann verbringst du Stunden mit Workarounds für ein Problem, das mit dem richtigen Tool in Minuten gelöst wäre.
Die Python-Community hat mehrere spezialisierte Tools entwickelt. Aber welcher Parser passt zu deinem Use-Case? Zum Glück gibt es klare Unterschiede, und die Top-5-Tools decken praktisch jeden Anwendungsfall ab.
1. PyMuPDF (fitz): Wenn es auf Geschwindigkeit ankommt
PyMuPDF ist in C geschrieben (mit Python-Bindings), und das merkst du in der Performance. Textextraktions-Benchmarks zeigen es deutlich:
Für ca. 7.000 Seiten eines PDFs braucht PyMuPDF 8 Sekunden, PyPDF2 benötigt 227 Sekunden. Das ist um Faktor 28 schneller.
Was kann PyMuPDF?
- Text extrahieren
- Images von Pages rendern
- Koordinaten und Metadaten auslesen
- Scanned PDFs mit Tesseract-OCR verarbeiten (optional)
Wo PyMuPDF schwach wird:
- Tabellen-Extraktion ist nicht die Stärke (es gibt keine built-in Table-Detection)
- Die API ist manchmal weniger Pythonic als bei anderen Tools
Hier ein praktisches Beispiel:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
import fitz # Das ist PyMuPDF # PDF öffnen doc = fitz.open('document.pdf') # Text von allen Seiten extrahieren full_text = "" for page_num in range(len(doc)): page = doc[page_num] text = page.get_text() full_text += text print(full_text) # Images von jeder Seite rendern und speichern for page_num, page in enumerate(doc): # Render mit 150 DPI pix = page.get_pixmap(matrix=fitz.Matrix(2, 2)) pix.save(f'page_{page_num}.png') # Koordinaten aller Rechtecke auf der Seite page = doc[0] for rect in page.get_drawings(): print(f'Rechteck bei: {rect.rect}') doc.close() |
Wann PyMuPDF nutzen?
- Du verarbeitest hunderte oder tausende PDFs täglich
- Performance ist non-negotiable
- Du brauchst Images oder rendering
- Du arbeitest mit komplexen PDF-Formaten
2. pdfplumber: Der Flexible Generalist
pdfplumber sitzt auf pdfminer.six auf und bietet eine viel höhere Abstraktionsstufe. Während PyMuPDF dir rohes Content-Material gibt, versteht pdfplumber die Struktur deines PDFs: wo Text sitzt, welche Linien Tabellenränder sind, wie Spalten aussehen.
Das ist genau das, was du für ernsthafte Datenextraktion brauchst.
Was kann pdfplumber?
- Exakte Text-Positionen (x, y Koordinaten für jedes Zeichen)
- Tabellen-Extraktion (mit konfigurierbaren Parametern)
- Linien, Rechtecke, Kurven auf der Page detektieren
- Crop und Filter nach Region
- Granulare Kontrolle über Layout-Parsing
Das Spannende: pdfplumber ist konfigurierbar. Du kannst genau steuern, wie Tabellen erkannt werden.
Beispiel: Tabellen aus Geschäftsberichten extrahieren:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
import pdfplumber with pdfplumber.open('financial_report.pdf') as pdf: # Erste Seite nehmen page = pdf.pages[0] # Alle Tabellen auf dieser Seite extrahieren tables = page.extract_tables() for i, table in enumerate(tables): print(f'Tabelle {i}:') for row in table: print(row) # Nur einen bestimmten Bereich croppen und analysieren cropped_page = page.crop((50, 50, 500, 300)) text = cropped_page.extract_text() print(text) # Alle Linien auf der Seite detektieren lines = page.lines rects = page.rects print(f'Gefundene Linien: {len(lines)}') print(f'Gefundene Rechtecke: {len(rects)}') |
Wo pdfplumber schwach wird:
- Langsamer als PyMuPDF (Layout-Analyse kostet Zeit)
- Scanned PDFs funktionieren nicht gut (es ist kein OCR integriert)
- Bei sehr großen Mengen PDFs wird die Performance zum Problem
Wann pdfplumber nutzen?
- Du extrahierst Tabellen oder strukturierte Daten
- Du brauchst Layout-Awareness
- Performance ist nicht das Top-Kriterium
- Du willst viel Kontrolle über die Extraktion
3. py-pdf/pypdf (ehemals PyPDF2): Der Pragmatiker
Das original pypdf ist älter. PyPDF2 war jahrelang Standard, aber das Projekt war fragmentiert (PyPDF3, PyPDF4, unzählige Forks). Jetzt gibt es py-pdf/pypdf, das PyPDF2 und seine Varianten vereint.
Was kann pypdf?
- Text extrahieren (basic)
- Seiten mergen, splitten, rotieren
- Metadaten lesen
- PDFs neuschreiben / kopieren
- Formulare lesen (begrenzt)
Was pypdf NICHT kann:
- Tabellen extrahieren
- Koordinaten verstehen
- Strukturelles Layout verstehen
- Images verarbeiten
Hier ein einfaches Beispiel für PDF-Manipulation:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
from pypdf import PdfReader, PdfWriter # PDF öffnen und lesen reader = PdfReader('original.pdf') writer = PdfWriter() # Seiten 0-4 extrahieren for i in range(min(5, len(reader.pages))): page = reader.pages[i] # Seite um 90 Grad rotieren page.rotate(90) writer.add_page(page) # Neue PDF schreiben with open('rotated_first_5_pages.pdf', 'wb') as f: writer.write(f) # Metadaten auslesen for page_num, page in enumerate(reader.pages): text = page.extract_text() print(f'Seite {page_num}: {len(text)} Zeichen') # Spezifische Seiten mergen merger = PdfWriter() for pdf_file in ['doc1.pdf', 'doc2.pdf', 'doc3.pdf']: with open(pdf_file, 'rb') as f: merger.append(PdfReader(f)) with open('merged.pdf', 'wb') as f: merger.write(f) |
Wann pypdf nutzen?
- Du brauchst PDF-Manipulation (keine Datenextraktion)
- Du willst minimale Dependencies
- Legacy-Code wartet auf Updates
- Du willst schnell ein PDF splitten/mergen
Das ehrliche Urteil: Für neue Datenextraktions-Projekte gibt es selten einen Grund, pypdf zu wählen. Es ist zu limitiert. Aber für reine PDF-Manipulation ist es das beste Tool.
4. Camelot: Der Tabellen-Spezialist
Camelot ist obsessed mit einer Sache: Tabellen aus PDFs extrahieren. Und es ist verdammt gut darin.
Das Besondere: Camelot hat zwei Algorithmen:
- Lattice: Für PDFs mit sichtbaren Linien (Gridlines)
- Stream: Für PDFs ohne Linien (Whitespace-basiert)
Und du kannst experimentieren, welcher besser funktioniert.
Was kann Camelot?
- Tabellen extrahieren (zwei verschiedene Algorithmen)
- Export zu Pandas DataFrame, CSV, JSON, Excel, HTML, Markdown, SQLite
- Qualitäts-Metriken pro Tabelle (accuracy, whitespace)
- Visuelle debugging Interface (plot tables, grids, contours)
- Scanned PDFs (mit ImageMagick + Tesseract)
Hier ein praktisches Beispiel:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
import camelot # Tabellen von PDF extrahieren tables = camelot.read_pdf('report.pdf') print(f'Gefundene Tabellen: {len(tables)}') for i, table in enumerate(tables): # Alle Tabellen mit accuracy über 0.5 nehmen if table.accuracy > 0.5: print(f'Tabelle {i}: {table.accuracy:.2%} accuracy') # Als DataFrame df = table.df print(df) # Oder direkt als CSV exportieren table.to_csv(f'table_{i}.csv') # Visuelles debugging: Schauen, was Camelot sieht # Lattice-Modus (für Tabellen mit sichtbaren Linien) tables_lattice = camelot.read_pdf( 'report.pdf', pages='1', flavor='lattice' ) # Stream-Modus (für Tabellen ohne Linien) tables_stream = camelot.read_pdf( 'report.pdf', pages='1', flavor='stream' ) # Beide vergleichen und beste auswählen if tables_lattice[0].accuracy > tables_stream[0].accuracy: tables_lattice[0].to_csv('best_table.csv') else: tables_stream[0].to_csv('best_table.csv') # Visual debugging: Plotten was Camelot sieht tables_lattice[0].plot() |
Wo Camelot schwach wird:
- Nur für Tabellen gemacht (du brauchst ein anderes Tool für allgemeinen Text)
- Bei scanned PDFs brauchst du zusätzliche Dependencies
- Performance ist nicht die Stärke
Wann Camelot nutzen?
- Dein Hauptproblem: Tabellen aus PDFs extrahieren
- Du brauchst konfigurierbare Table-Detection
- Du willst ein spezialisiertes Tool, das wirklich gut in seiner Nische ist
5. pdfminer.six: Wenn es um Details geht
pdfminer.six ist unter der Haube. Es ist die Basis von pdfplumber und powert viele andere Tools. Aber du kannst es auch direkt nutzen.
Was macht pdfminer.six speziell?
- Character-Level Extraktion (du kriegst Fonts, Positionen, Größen)
- Layout-Analyse (versteht Struktur)
- Vollständige Kontrolle über PDF-Parsing
- Konvertierung zu XML, HTML, etc.
Das ist sehr low-level. Wenn pdfplumber für dich nicht granular genug ist, probiere pdfminer.six.
Ein Beispiel mit Character-Level Control:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
from pdfminer.high_level import extract_pages from pdfminer.layout import LADParams, LTTextBox, LTChar # Seiten mit Layout-Analyse extrahieren for page_layout in extract_pages('document.pdf'): print(f'Seite Höhe: {page_layout.height}, Breite: {page_layout.width}') for element in page_layout: # Alle Text-Boxen if isinstance(element, LTTextBox): print(f'Text: {element.get_text()}') print(f'Position: x0={element.x0}, y0={element.y0}') print(f'Font info: {element.get_text()}') # Alle Zeichen in dieser Box for line in element: for char in line: if isinstance(char, LTChar): print(f'Char: {char.get_text()}, Font: {char.fontname}, Size: {char.height}') |
Wo pdfminer.six schwach wird:
- Low-level API ist komplex
- Performance ist nicht optimiert
- Tabellen-Extraktion ist nicht built-in
- Die Kurve Datenextraktion ist steil
Wann pdfminer.six nutzen?
- Du brauchst granulare Kontrolle über Font-Informationen
- Du customizest pdfplumber und brauchst Zugriff auf Internals
- Du experimentierst mit PDF-Struktur
Der Vergleich auf einen Blick
| Tool | Speed | Tabellen | Images | Struktur | Einfachheit | Am Besten für |
|---|---|---|---|---|---|---|
| PyMuPDF | 10/10 | 4/10 | 10/10 | 5/10 | 6/10 | Große Mengen, Rendering |
| pdfplumber | 6/10 | 9/10 | 5/10 | 10/10 | 8/10 | Strukturierte Daten, Tabellen |
| pypdf | 7/10 | 2/10 | 2/10 | 3/10 | 9/10 | PDF-Manipulation |
| Camelot | 5/10 | 10/10 | 2/10 | 3/10 | 8/10 | Nur Tabellen |
| pdfminer.six | 4/10 | 3/10 | 2/10 | 10/10 | 4/10 | Character-Level Control |
Die Entscheidungs-Matrix
Ich muss Text aus 1000 PDFs extrahieren, schnell:
PyMuPDF. Punkt. Nichts anderes kommt nah ran. 8 Sekunden vs. 227 Sekunden ist nicht lustig, das ist existenziell.
Ich muss Tabellen aus Reports extrahieren, mehrfach im Monat:
pdfplumber. Es versteht Layout, es ist flexible, und du kannst debuggen. Oder Camelot wenn Tabellen deine einzige Aufgabe sind.
Ich muss PDFs mergen/splitten/rotieren:
pypdf. Einfach, pragmatisch, gut darin.
Ich muss Font-Details, Positions-Information, absolute Kontrolle:
pdfminer.six. Aber sei bereit, Zeit zu investieren.
Ich habe OCR-Anforderungen (scanned PDFs):
Keine dieser Libraries ist ideal. Guck dir PyMuPDF mit Tesseract an.
Python: Pro-Tipps zur PDF-Verarbeitung
1. Kombiniere mehrere Tools
Du brauchst NICHT ein Tool für alles. Tatsächlich: Nutze PyMuPDF um schnell Text zu extrahieren, nutze pdfplumber wenn du merkst dass Layout-Parsing nötig ist. Moderne Automatisierungen kombinieren mehrere Parser:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import fitz import pdfplumber # Schnelle Text-Extraktion mit PyMuPDF with fitz.open('doc.pdf') as doc: full_text = '\n'.join([page.get_text() for page in doc]) # Dann, wenn Tabellen verdächtig sind, nutze pdfplumber if 'Tabelle' in full_text or '€' in full_text: with pdfplumber.open('doc.pdf') as pdf: for page in pdf.pages: tables = page.extract_tables() # Verarbeite Tabellen |
2. Benchmarke dein Use-Case
Theorie ist schön, aber real-world PDFs sind chaotisch. Schreib schnell einen Test mit deinen echten PDFs:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
import time import fitz import pdfplumber test_pdf = 'your_production_pdf.pdf' # PyMuPDF start = time.time() with fitz.open(test_pdf) as doc: text = '\n'.join([page.get_text() for page in doc]) print(f'PyMuPDF: {time.time() - start:.2f}s') # pdfplumber start = time.time() with pdfplumber.open(test_pdf) as pdf: text = '\n'.join([page.extract_text() for page in pdf.pages]) print(f'pdfplumber: {time.time() - start:.2f}s') |
Der schneller ist für dich der richtige.
3. Error Handling für ganz spezielle PDFs
Deine PDFs sind ‘speziell’ ? Encoding-Issues, Missing Fonts, Corrupted Streams etc.
Arbeite mit Fallback-Methoden:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
import fitz import logging logger = logging.getLogger(__name__) def safe_extract_text(pdf_path): try: with fitz.open(pdf_path) as doc: text = '' for page_num, page in enumerate(doc): try: text += page.get_text() except Exception as e: logger.warning(f'Fehler auf Seite {page_num}: {e}') # Fallback: Try alternative extraction method try: text += page.get_text('blocks') except: logger.error(f'Seite {page_num} nicht zu retten') return text except Exception as e: logger.error(f'PDF öffnen fehlgeschlagen: {e}') return None |
Fazit
Jede der 5 Libraries hat Stärken und Schwächen.
Aber die Entscheidung wird einfacher, wenn Foglendes weißt:
- PyMuPDF: Wenn Geschwindigkeit kritisch ist
- pdfplumber: Wenn Layout und Struktur wichtig sind
- pypdf: Wenn du PDFs manipulierst statt Daten extrahierst
- Camelot: Wenn Tabellen deine Spezialität sind
- pdfminer.six: Wenn du granulare Kontrolle brauchst
Die beste Strategie? Fang mit pdfplumber an. Es ist flexible genug für 80% der Use-Cases. Wenn die Performance zum Problem wird, wechsle zu PyMuPDF. Wenn Tabellen wichtig sind, nimm Camelot.
Nutze das Tool, das am wenigsten Zeit kostet und am besten funktioniert. Nicht das, das am coolsten klingt :-)
Lies mehr zu PDF-Processing