Files
docu_build/doc/plan_fortna_extraktion.md
T
Michael StanglandClaude Opus 4.8 e7aa3b4e4b feat: Fortna-Extraktion nach chapters/ + Sphinx-PDF-Build
Skripte zum Befuellen der Kapitelstruktur aus dem Fortna-Rohmaterial und
Aufbau eines vollstaendigen Sphinx/LaTeX-Builds (nur Code/Config/Doku,
generierte RST/Bilder/PDFs und Rohmaterial via .gitignore ausgeschlossen).

- lib/fortna_inventory.py: Rohmaterial scannen, Sprache+Zielkapitel+Aktion
  zuordnen, results/fortna_inventory.json schreiben
- lib/fortna_convert_chapters.py: 5 Hauptanleitungen volltextig (Text+Bilder)
  konvertieren, Verzeichnislisten (index.de.rst) fuer uebrige Kapitel
- lib/fortna_init_project.py: projekte/fortna/ (anlage.json, overrides, images)
- lib/build_index.py: index.rst mit toctrees aus chapters/**/*.de.rst generieren
- lib/extract_products.py: Symbolfont-Zeichen (PUA) auf Unicode mappen (clean_pua)
- conf.py: Sphinx-Build (lualatex, babel statt polyglossia, iconpackage=none)
- bin/: .bat/.sh-Wrapper fuer alle Skripte + build_pdf
- doc/: Konzept-Plan (plan_fortna_extraktion.md) und lib-Skript-Uebersicht
- requirements.txt: Sphinx + myst-parser ergaenzt

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-09-23 13:23:32 +02:00

15 KiB
Raw Blame History

Konzept: Fortna-Extraktion nach chapters/ + Projektordner fortna/

Status: Umgesetzt (erster vollständiger Durchlauf inkl. PDF-Build). Antworten aus der Rückfragerunde sind eingearbeitet (siehe Abschnitt "Entscheidungen"). Der tatsächliche Ist-Stand ist unten unter "Umsetzung / Ist-Stand" dokumentiert.

Umsetzung / Ist-Stand

Implementiert wurden vier Python-Skripte in lib/ mit bin/-Wrappern (.bat + .sh):

Skript Zweck Wrapper
lib/fortna_inventory.py Scannt das Rohmaterial, ordnet jede Datei Sprache + Zielkapitel + Aktion zu, schreibt results/fortna_inventory.json. bin/fortna_inventory.*
lib/fortna_convert_chapters.py Volltext+Bilder für die 5 DE-Hauptanleitungen, Verzeichnislisten (index.de.rst) für alle übrigen Kapitel. --dry-run (Default) / --apply. bin/fortna_convert_chapters.*
lib/fortna_init_project.py Legt projekte/fortna/ an (anlage.json, overrides/, images/, README.md). bin/fortna_init_project.*
lib/build_index.py Generiert index.rst mit toctrees aus allen chapters/**/*.de.rst. (in build_pdf.*)
bin/build_pdf.* Kompletter PDF-Build: index → sphinx-build -b latex → latexmk -lualatex. —

Ergebnis des ersten Laufs:

  • 5 Hauptanleitungen volltextig konvertiert (Betriebs-/Wartungsanleitung, Funktionsbeschreibung ILS/OMNIFLO/LoadingLoop), zusammen ~13.500 Textblöcke + mehrere Hundert entduplizierte Bilder.
  • 9 Verzeichnislisten erzeugt (Zertifikate, Lieferantendoku nach Gewerk, Notstopp, Prüfberichte).
  • projekte/fortna/ mit anlage.json-Platzhalter angelegt.
  • Vollständiger PDF-Build erfolgreich: _build/latex/Fortna_Dokumentation_DE.pdf, ~670 Seiten, latexmk-Exit 0, keine LaTeX-Fehler.

Umgebung / Build-Voraussetzungen (bereits erfüllt)

  • Sphinx 9.1.0 + myst-parser 5.1.0 im .venv (ergänzt in requirements.txt).
  • LaTeX: MiKTeX unter C:\Program Files\MiKTeX\ (lualatex/latexmk vorhanden).
  • conf.py erzeugt: LaTeX-Engine lualatex, babel statt polyglossia (polyglossia 2.13 wirft unter lualatex einen bidi-Fehler), iconpackage=none (FontAwesome7 in MiKTeX bricht unter lualatex ab). Beides in conf.py kommentiert.

Behobene Extraktionsprobleme

  • Symbolfont-Zeichen (Wingdings/Symbol Private-Use-Area, z. B. Aufzählungs-Bullet U+F0B7): in extract_products.py via clean_pua() auf echte Unicode-Zeichen (•, →, ✓) gemappt, restliche PUA-Zeichen entfernt. Vorher erschienen leere Kästchen im PDF.

Bekannte Restpunkte (nicht Teil des Auftrags-Scopes)

  • Zwei Fremd-Altdateien aus früheren convert_to_rst.py-Testläufen sind noch im Baum und vom Build ausgeschlossen (conf.py + build_index.py SKIP-Liste): 02_sicherheit/risikobewertung/rb_fortna_...de.rst (unvollständiger Bildbestand) und 00_inhaltsverzeichnis/contens_obsah_...de.rst (keine RST-Überschrift). Zwei weitere Altdateien in 10_anhang/ (Motor/Getriebe) sind noch im toctree und zeigen typische Extraktionsartefakte – bei Bedarf mit fortna_convert_chapters.py sauber neu erzeugen.
  • Tabellen (z. B. Änderungshistorie) werden weiterhin als Einzelzeilen extrahiert, nicht als RST-Tabelle rekonstruiert (wie im Konzept angekündigt).

Ausgangslage

  • Reales Fortna-Rohmaterial liegt in c:\10-Develop\projekte\Fortna\ (zusätzliches Arbeitsverzeichnis dieser Session, nicht im Repo). Struktur wie in doc/Fortna.txt dokumentiert (00_CONTENTS_NOTES … 05_SUPPLIER_DOC), Versionsstände dort sind aktueller als in doc/Fortna.txt (z. B. Betriebsanleitung V2.4 statt V2.3, Wartungsanleitung V2.3, ILS V2.2, OMNIFLO V1.1, LoadingLoop V2.3). doc/Fortna.txt/doc/Fortna-size.txt sind nur noch als Struktur-Referenz zu verstehen, nicht als Quelle für den Extraktionslauf.
  • chapters/ (Base-Repo-Gerüst) existiert bereits vollständig mit .gitkeep-Platzhaltern gemäß doc/kapitelstruktur.md. 06_steuerung/loading_loop/ wurde testweise mit convert_to_rst.py aus der LoadingLoop-Word-Datei befüllt (2 RST + 74 Bilder). Qualität ist noch unzureichend: Kopf-/Fußzeilen (Firmenadresse, Kontaktdaten) landen als normale Absätze im Fließtext, Tabellen (Änderungshistorie) werden zu einzelnen Zeilen ohne Tabellenstruktur zerlegt. Das ist ein bekanntes Problem der aktuellen _html_to_blocks-Logik in convert_to_rst.py und wird im Zuge dieser Arbeit mit adressiert (siehe Abschnitt "Bekannte Schwachstellen").
  • Vorhandene Skripte in lib/ (siehe doc/lib_skripte.md):
    • convert_to_rst.py: .docx/Word-PDF → RST, erkennt Zielkapitel nur anhand Dateiname-Pattern im Root eines Ordners, kein Verständnis für den verschachtelten Fortna-Sprachordner-Baum.
    • extract_products.py: Produktprogramm-PDFs → Bilder + RST (bereits fertig genutzt für data/Produktprogramm).
    • jsonFromXlsx.py, extract_ids.py, project_from_xlsx.py: Stücklisten-Auswertung, für diese Aufgabe nicht direkt relevant.
  • Kein Skript kennt bisher die komplette Fortna-Ordnerstruktur (Lieferantendoku-Baum, Layouts, Schaltpläne, Prüfberichte) und keines erzeugt den projektspezifischen Ordner (anlage.json, overrides/, images/) gemäß doc/Kernkonzepte.md.

Entscheidungen (aus Rückfragen)

Frage Entscheidung
Lieferantendoku (~250 PDFs: SEW, Siemens, Leuze, Cognex, MiTek, Aventics, …) Nur Verzeichnisliste, keine Kopie. RST-Referenztabelle mit Pfaden auf das Originalverzeichnis.
Sonstige PDFs (Zertifikate, Konfigurationsbeschreibung, Layouts, Schaltpläne, Notstopp/Bereichsstopp, Prüfberichte, Ersatzteilliste) Gleiche Behandlung wie Lieferantendoku: nur Verzeichnisliste, keine Kopie nach chapters/.
Volltext-Konvertierung (Text + Bilder → RST) Nur die 5 Hauptanleitungen: Betriebsanleitung, Wartungsanleitung, Funktionsbeschreibung ILS, Funktionsbeschreibung OMNIFLO, Funktionsbeschreibung LoadingLoop.
Projektordner-Ort projekte/fortna/ innerhalb dieses Repos (docu_build), pragmatisch für jetzt; spätere Auslagerung in eigenes Repo bleibt möglich.
Sprachumfang Nur Deutsch in diesem Durchlauf. Namenskonvention {name}.de.rst einhalten, EN/CZ als späterer zweiter Durchlauf vorgesehen.
Quelle c:\10-Develop\projekte\Fortna\ (aktueller Stand), nicht doc/Fortna.txt.
Umgang mit bestehendem chapters/06_steuerung/loading_loop/ Überschreiben/neu erzeugen – konsistent aus einem Guss statt Altbestand stehen lassen.

Zielstruktur (Ergebnis nach Lauf)

chapters/
  01_zertifikate/
    konformitaetserklaerung/index.de.rst        # Verzeichnisliste -> Originalpfade
    konfigurationsbeschreibung/index.de.rst
  02_sicherheit/                                  # unverändert (kein Fortna-Rohmaterial 1:1 zuordenbar)
  03_anlagenbeschreibung/                         # unverändert (Modul-Mechanismus, nicht Teil dieser Aufgabe)
  04_betrieb/betriebsanleitung/
    betriebsanleitung_500592_135776_v2_4.de.rst   # Volltext + Bilder
    images/img_001.png ...
  05_wartung/wartungsanleitung/
    wartungsanleitung_500592_v2_3.de.rst          # Volltext + Bilder
    images/...
  06_steuerung/
    ils/funktion_steuerung_ils_500592_v2_2.de.rst # Volltext + Bilder
    omniflo/funktion_steuerung_omniflo_500592_v1_1.de.rst
    loading_loop/funktion_steuerung_loadingloop_500592_v2_3.de.rst  # neu erzeugt, ersetzt Altbestand
  07_ersatzteile/index.de.rst                     # Verzeichnisliste -> Originalpfad SPARE_PARTS PDF
  08_lieferantendoku/
    antriebe/index.de.rst                         # Verzeichnisliste SEW, NORD, Leantechnik, DTS
    elektrik/index.de.rst                         # Siemens, Leuze, Cognex, Werma, ...
    pneumatik/index.de.rst                        # Aventics, ITS
    stahlbau/index.de.rst                         # MiTek (As-Built, Statik, Zertifikate, ...)
    sicherheitseinrichtungen/index.de.rst          # ABS Sicherheitslinie
  09_technische_unterlagen/
    layouts/mechanisch/index.de.rst
    layouts/elektrisch/index.de.rst
    schaltplaene/index.de.rst
    notstopp/index.de.rst
    bereichsstopp/index.de.rst
  10_anhang/
    pruefberichte/index.de.rst

projekte/
  fortna/
    anlage.json            # Projektmetadaten (Platzhalter/Vorschlag, manuell nachzuschärfen)
    overrides/              # leer angelegt, Struktur gemäß Kernkonzepte.md
    images/                 # leer angelegt (projektspezifische Bilder, Kundenlogo etc.)
    README.md               # kurze Erläuterung was hier reinkommt

Jede index.de.rst-Verzeichnisliste enthält eine Tabelle: Dateiname, Hersteller/Kategorie (aus Ordnername abgeleitet), Originalpfad (relativ zu einer konfigurierbaren Basis, z. B. PV_FORTNA_SOURCE), Dateigröße. Kein PDF wird kopiert oder eingebettet – das hält den Kapitelbaum schlank und vermeidet Redundanz zum Rohmaterial, das ohnehin an anderer Stelle (Nextcloud/Projektordner) verwaltet wird.

Geplante Skripte (in lib/)

1. fortna_inventory.py (neu)

Scannt c:\10-Develop\projekte\Fortna\ rekursiv und baut ein Inventar (JSON) aller Dateien mit: Pfad, Größe, erkannte Sprache (aus Ordnername: *_DE*/*_EN*/*_CZ*/*original* → de), vermutetem Fortna-Kapitel (oberste zwei Ebenen) und vermutetem Ziel-Kapitel gemäß Mapping-Tabelle aus doc/kapitelstruktur.md. Dient als Kontrollartefakt (results/fortna_inventory.json), auf dessen Basis sich beide folgenden Skripte konfigurieren bzw. dessen Output sich manuell prüfen lässt, bevor tatsächlich geschrieben wird (--dry-run Default, --apply zum Ausführen).

Grund für ein separates Inventarskript: 387 Dateien über 6 Top-Level-Ordner mit inkonsistenter Sprachordner-Benennung (01_DE_original, 01_EN_original, 1_EN_original [Tippfehler im Quellbaum], 02_CZ, 03_CZ_pro_celé_zařízení, …) – ein Trockenlauf mit Report ist nötig, um Mapping-Lücken zu erkennen, bevor Dateien verschoben/verarbeitet werden.

2. fortna_convert_chapters.py (neu)

Nutzt das Inventar aus Schritt 1 (oder scannt bei Bedarf direkt) und führt zwei Aktionsarten aus:

  • Volltext-Konvertierung für die 5 Hauptanleitungen: ruft die vorhandene Konvertierungslogik aus convert_to_rst.py wieder, aber mit expliziter Quelldatei-Liste (kein Verzeichnis-Scan) und fest zugeordnetem Zielkapitel (aus der Tabelle unten), statt der generischen CHAPTER_MAPPING-Heuristik. Überschreibt bestehende Ziel-RSTs/Bilder vollständig (Ordnerinhalt vorher leeren, dann neu schreiben).
  • Verzeichnislisten-Generierung für alle übrigen Kapitel (Zertifikate, Layouts, Schaltpläne, Notstopp/Bereichsstopp, Prüfberichte, Ersatzteile, Lieferantendoku): läuft über die im Inventar erkannten Dateien je Zielordner und rendert eine index.de.rst mit RST-list-table (Dateiname, Pfad, Größe).

Fest zugeordnete Hauptanleitungen (Quelle → Ziel):

Quelldatei (DE, aktuellster Stand in projekte/Fortna) Zielkapitel
02_INSTRUCTIONS.../01_DE_original/01_BETRIEBSANLEITUNG_500592_135776_V2.4.pdf 04_betrieb/betriebsanleitung/
02_INSTRUCTIONS.../01_DE_original/02_WARTUNGSANLEITUNG_500592_V2.3.pdf 05_wartung/wartungsanleitung/
02_INSTRUCTIONS.../01_DE_original/03_FUNKTION_STEUERUNG_ILS_500592_V2.2.pdf 06_steuerung/ils/
02_INSTRUCTIONS.../01_DE_original/04_FUNKTION_STEUERUNG_OMNIFLO_500592_V1.1.pdf 06_steuerung/omniflo/
02_INSTRUCTIONS.../01_DE_original/05_FUNKTION_STEUERUNG_LOADING_LOOP_500592_V2.3.pdf 06_steuerung/loading_loop/ (ersetzt Altbestand)

Alle fünf sind PDFs (keine .docx im Quellordner mehr vorhanden), daher wird der is_word_pdf()-Pfad aus convert_to_rst.py verwendet (pdfminer-Textextraktion). Die extra extract_products.py-Textheuristik (Schriftgrößen-basierte Überschriftenerkennung, Kopf-/Fußzeilen-Ausschluss nach Y-Position) ist für Word-erstellte PDFs wie diese robuster als die aktuelle convert_to_rst.py-Textheuristik (siehe Bekannte Schwachstellen) – Vorschlag: die Extraktionsroutine aus extract_products.py (extract_text_to_rst, _is_noise, extract_images) wiederverwenden/verallgemeinern statt der schwächeren pdfminer-Variante aus convert_to_rst.py.

3. fortna_init_project.py (neu)

Legt projekte/fortna/ an: anlage.json (Platzhalter mit Projektnummer 500592/KA135776, Sprache ["de"], normen_region offen als TODO), leere overrides/- und images/-Ordner mit .gitkeep, sowie ein kurzes README.md. Einmaliger Lauf, kein Datei-Scan nötig – im Wesentlichen ein Gerüst-Generator.

Bekannte Schwachstellen der bisherigen Konvertierung (zu beheben)

Der Altbestand in chapters/06_steuerung/loading_loop/ zeigt zwei konkrete Probleme der aktuellen convert_to_rst.py-Logik, die für die 5 Hauptanleitungen behoben werden sollten:

  1. Kopf-/Fußzeilen als Fließtext: Firmenadresse, Kontaktdaten, Projektnummer erscheinen als normale Absätze mitten im Dokument (weil pdfminer.high_level.extract_text keine Positionsinformation liefert, mit der man Kopf-/Fußzeilen herausfiltern könnte). extract_products.py löst das bereits über page.get_text("dict") mit Y-Positions-Filter (bbox[1] < 100 / bbox[3] > page_height - 50) – diese Technik übernehmen.
  2. Tabellen zerfallen in Einzelzeilen: Die Änderungshistorie-Tabelle wird zu einer Folge einzelner Absätze ohne Tabellenstruktur. Vorschlag für ersten Wurf: Tabellen nicht als RST-Table rekonstruieren (zu fehleranfällig aus PDF-Text), sondern als eingerückten .. code-block:: oder einfache Aufzählung kennzeichnen, mit .. todo:: Tabelle manuell nachbearbeiten-Marker – ehrlich statt falsch-schön.

Offene Punkte / Annahmen, die ich getroffen habe

  • Ich gehe davon aus, dass PV_FORTNA_SOURCE (oder ein --source-dir-Argument) als neue Umgebungsvariable/Parameter eingeführt wird, die auf c:\10-Develop\projekte\Fortna\ zeigt, da dieser Pfad außerhalb des Repos liegt und nicht über PV_DATA/PV_EXAMPLES erreichbar ist.
  • 02_sicherheit/ und 03_anlagenbeschreibung/ bleiben in diesem Durchlauf unangetastet – es gibt keine 1:1-Quelle dafür in projekte/Fortna/ (Risikobewertung liegt als separate .docx-Dateien direkt im Repo-Root von chapters/, siehe Git-Status, nicht Teil dieser Aufgabe).
  • Die generierten index.de.rst-Verzeichnislisten verweisen auf absolute oder repo-relative-konfigurierbare Pfade zum Rohmaterial – das bedeutet, das Zielsystem (Sphinx) bekommt keine eigenständig lauffähige Doku ohne Zugriff auf projekte/Fortna/. Das ist so gewollt gemäß der Entscheidung "nur Verzeichnisliste", sollte aber vor dem produktiven PDF-Build nochmal bewusst bestätigt werden (spätestens beim ersten sphinx-build-Versuch fehlen dann die Downloads/Links).

Nächste Schritte

  1. Dieses Konzept abstimmen (insb. Umgang mit 02_sicherheit/Risikobewertung-Docx im Root von chapters/, sowie die Pfad-Referenzierung in den Verzeichnislisten).
  2. fortna_inventory.py implementieren und Trockenlauf-Report gegen projekte/Fortna/ prüfen.
  3. fortna_convert_chapters.py implementieren (inkl. Wiederverwendung der extract_products.py-Textextraktion), auf 5 Hauptanleitungen anwenden, Ergebnis stichprobenhaft gegenlesen.
  4. fortna_init_project.py implementieren, projekte/fortna/ anlegen.
  5. bin/-Wrapper-Skripte (.bat/.sh) für alle drei ergänzen, analog bestehender Konvention.