Ein Python-Tool mit grafischer Benutzeroberfläche zur intelligenten Textextraktion aus PDFs. Primär wird der eingebettete Textlayer genutzt; OCR dient als automatischer Fallback für Seiten ohne verwertbaren Layer.
pdf_extractor.py Hauptprogramm (GUI + Logik)
install_linux.sh Automatisches Installations-Script
run_pdf_extractor.sh Start-Script (MESA-Fix enthalten)
README.md Diese Datei
Nach der Installation wird zusätzlich angelegt:
pdf_extractor_venv/ Python Virtual Environment
chmod +x install_linux.sh
./install_linux.sh # einmalig
./run_pdf_extractor.sh # danach zum StartenUm eine neue Version einzuspielen, reichen drei Schritte:
# 1. Neues pdf_extractor.py in den Ordner kopieren
cp /pfad/zur/neuen/pdf_extractor.py ~/pdf_extractor/pdf_extractor.py
# 2. Falls neue Python-Pakete hinzugekommen sind:
source pdf_extractor_venv/bin/activate
pip install --quiet PyQt5 PyMuPDF pdf2image pytesseract Pillow \
opencv-python-headless numpy pdfplumber
deactivate
# 3. Programm starten – fertig
./run_pdf_extractor.shEin vollständiges Neu-Installieren ist nur nötig wenn:
- die Datei
pdf_extractor_venv/fehlt oder beschädigt ist, - neue System-Pakete (Tesseract, poppler) benötigt werden, oder
- die Python-Version gewechselt wurde.
In diesen Fällen:
rm -rf pdf_extractor_venv
./install_linux.sh| Komponente | Mindestversion | Hinweis |
|---|---|---|
| Linux | Debian/Ubuntu | andere Distros: manuell |
| Python | 3.8+ | 3.12 wird unterstützt |
| Tesseract OCR | 5.x | wird vom Install-Script geholt |
| RAM | 2 GB | große PDFs: 4 GB empfohlen |
| Festplatte | ~600 MB | für alle Abhängigkeiten |
Das Install-Script erledigt automatisch:
- Python-Prüfung und
python3-venv-Installation - Tesseract OCR (inkl. Deutsch-Sprachpaket, weitere optional)
- poppler-utils (für PDF→Bild-Konvertierung)
- Virtual Environment
pdf_extractor_venv/ - Alle Python-Pakete (isoliert in der venv)
- Erstellung von
run_pdf_extractor.sh
# System-Pakete
sudo apt-get install tesseract-ocr tesseract-ocr-eng tesseract-ocr-deu \
poppler-utils python3-venv
# Virtual Environment
python3 -m venv pdf_extractor_venv
source pdf_extractor_venv/bin/activate
# Python-Pakete
pip install PyQt5 PyMuPDF pdf2image pytesseract Pillow \
opencv-python-headless numpy pdfplumber./run_pdf_extractor.shIn der GUI:
- PDF auswählen – Datei wählen
- Optionen einstellen (alle standardmäßig aktiv)
- Verarbeitung starten
- Fortschrittsbalken und Statuszeile zeigen den aktuellen Schritt
- Als TXT speichern
Der Abbrechen-Button stoppt die Verarbeitung; bereits verarbeitete Seiten sind als Zwischendatei vorhanden (wenn Zwischenspeicherung aktiv).
| Option | Beschreibung |
|---|---|
| Tabellen erkennen | Extrahiert Tabellen via pdfplumber, gibt sie als [TABELLE N]…[/TABELLE N] aus |
| Kopf-/Fußzeilen entfernen | Dreistufig: Schriftgröße ≤ 9 pt · Randzone (6 %) · Häufigkeitsanalyse |
| Initialen normalisieren | A.B.C. → ABC (nur aufeinanderfolgende Einzelbuchstaben) |
| Silbentrennung aufheben | Soft-Hyphen (U+00AD) und harte Trennstriche am Zeilenende |
| Zwischenspeichern | Alle 20 Seiten wird eine *_autosave_bis_sN.txt-Datei geschrieben |
Seiten mit zwei (oder mehr) Textspalten werden korrekt verarbeitet. Die Spaltenerkennung nutzt ein X-Histogramm: Das Programm erstellt ein Belegungsraster über die Seitenbreite und sucht den breitesten unbelegten Bereich in der Seitenmitte als Spaltentrennbereich.
Vorher (falsch – Y-sortiert, Spalten vermischt):
"Human apathy has always..." ← Spalte L, Zeile 1
"A local caern, a center..." ← Spalte R, Zeile 1
"and most difficult foes..." ← Spalte L, Zeile 2
Nachher (korrekt – Spalte L komplett, dann Spalte R):
"Human apathy has always..." ← Spalte L, Zeile 1
"and most difficult foes..." ← Spalte L, Zeile 2
...
"A local caern, a center..." ← Spalte R, Zeile 1
Einspaltige Seiten (Titel, Kapitelstart, volle Breite) werden automatisch erkannt und unverändert behandelt.
Zierbuchstaben (Schriftgröße ≥ 20 pt, Einzelzeichen) werden korrekt mit dem nachfolgenden Textblock zusammengefügt:
vorher: H
uman apathy has always …
nachher: Human apathy has always …
- Schriftgröße ≤ 9 pt
- Y-Position im oberen/unteren Randbereich (6 % der Seitenhöhe)
- Häufigkeitsanalyse: Texte ≥ 35 %, reine Zahlen ≥ 60 % aller Seiten
Seitenzahlen werden nur als eigenständige Zeile entfernt – eingebettete Zahlen im Fließtext bleiben erhalten.
vorher: loneli-
ness and rage …
nachher: loneliness and rage …
Behandelt: Soft-Hyphen (U+00AD), harte Trennstriche am Zeilenende, Artefakte an Seitengrenzen.
Alle Bullet-Symbole (■ ● • ○ ▪ ▸ ◆ □) und das OCR-Artefakt
0 am Zeilenanfang werden durch - ersetzt.
Tesseract läuft mit eng+deu – verbessert die Erkennungsqualität
für gemischte und deutschsprachige Dokumente.
Ab 80 Seiten werden Seiten einzeln in Bilder konvertiert statt
alle gleichzeitig. Das verhindert den SIGKILL-Fehler (Getötet)
bei PDFs mit > 100 Seiten durch RAM-Überlauf.
Alle 20 Seiten wird eine Zwischendatei geschrieben. Bei einem Absturz oder Abbruch geht kein bereits verarbeiteter Text verloren.
| Textlayer-Qualität | Strategie |
|---|---|
| ≥ 30 % | Textlayer primär, OCR-Fallback für schwache Seiten |
| < 30 % | OCR primär (gescannte / Bild-PDFs) |
Standard: Englisch + Deutsch (eng+deu).
Weitere Sprachen installieren:
sudo apt-get install tesseract-ocr-fra # Französisch
sudo apt-get install tesseract-ocr-spa # Spanisch
sudo apt-get install tesseract-ocr-ita # Italienisch
tesseract --list-langs # alle verfügbaren SprachenSprache im Code anpassen (pdf_extractor.py, Konstante OCR_LANG):
OCR_LANG = "eng+deu+fra" # BeispielMESA: error: ZINK: failed to choose pdev
glx: failed to create drisw screen
→ Bereits behoben: run_pdf_extractor.sh setzt automatisch
LIBGL_ALWAYS_SOFTWARE=1 und GALLIUM_DRIVER=softpipe.
./run_pdf_extractor.sh: Zeile 18: 5215 Getötet python3 pdf_extractor.py
→ RAM-Problem. Ab 80 Seiten arbeitet das Script automatisch seitenweise. Zusätzlich kann Swap vergrößert werden:
sudo fallocate -l 4G /swapfile2
sudo chmod 600 /swapfile2
sudo mkswap /swapfile2
sudo swapon /swapfile2sudo apt-get install python3-venv python3-full
# Python 3.12:
sudo apt-get install python3.12-venvsudo apt-get install tesseract-ocr tesseract-ocr-eng tesseract-ocr-deurm -rf pdf_extractor_venv
./install_linux.sh→ Bereits behoben: run_pdf_extractor.sh leert
QT_QPA_PLATFORM_PLUGIN_PATH.
| Paket | Zweck |
|---|---|
| PyQt5 | GUI |
| PyMuPDF (fitz) | PDF-Textlayer-Extraktion, Blockanalyse |
| pdfplumber | Tabellenerkennung |
| pdf2image | PDF→PIL-Bild (via poppler) |
| pytesseract | Tesseract-OCR-Anbindung |
| Pillow | Bildverarbeitung |
| opencv-python-headless | Morphologische Operationen (headless) |
| numpy | Numerische Operationen |
PDF öffnen (PyMuPDF)
│
├─ Textlayer-Qualität prüfen (Stichprobe 6 Seiten)
├─ Kopf-/Fußzeilen-Muster sammeln (alle Seiten)
│
└─ Seitenweise:
├─ Eingebettenen Text extrahieren
│ ├─ Kopf-/Fußzeilen ignorieren (sz + Y-Zone)
│ ├─ Spalten erkennen (X-Histogramm, 8-px-Bins)
│ ├─ Blöcke je Spalte Y-sortieren, Spalten L→R
│ ├─ Dropcap-Erkennung und -Verbindung
│ └─ Soft-Hyphen-Bereinigung
├─ Falls Qualität < 30 %: OCR (Tesseract eng+deu)
├─ Tabellen ergänzen (pdfplumber)
└─ Zwischenspeicherung alle 20 Seiten
│
└─ Nachbearbeitung:
├─ Kopf-/Fußzeilen-Muster entfernen
├─ Initialen normalisieren
├─ Bullet-Symbole → '-'
├─ Text bereinigen
└─ Globale Soft-Hyphen-Bereinigung (Seitengrenzen)
cd ..
rm -rf pdf_extractor/Tesseract und poppler bleiben installiert (System-Pakete).
| Version | 3.2 |
| Erstellt | 2026 |
| Lizenz | Frei für persönlichen und kommerziellen Gebrauch |
Seiten mit zwei Textspalten werden korrekt verarbeitet. Die Spaltenerkennung nutzt ein X-Histogramm (v4):
v3.2-Verbesserung: Nur Blöcke, die klar einer Spalte angehören (beginnen und enden innerhalb der eigenen Seitenhälfte), fließen ins Histogramm ein. Zentrierte Blöcke (Kapitelüberschriften, Zitate wie „Table of Contents" mit x0=113..x1=499) wurden in v3.1 fälschlicherweise ins Histogramm aufgenommen und füllten die Lücke zwischen den Spalten — wodurch die Spalten-Erkennung fehlschlug.
Vorher (falsch – Y-sortiert, Spalten vermischt):
"Human apathy has always..." ← Spalte L, Zeile 1
"A local caern, a center..." ← Spalte R, Zeile 1 (falsch früh)
"and most difficult foes..." ← Spalte L, Zeile 2
Nachher (korrekt – Spalte L komplett, dann Spalte R):
"Human apathy has always..." ← Spalte L, Zeile 1
"and most difficult foes..." ← Spalte L, Zeile 2
...
"A local caern, a center..." ← Spalte R, Zeile 1
Einspaltige Seiten (Titel, volle Breite) werden automatisch erkannt.