# conversione — PDF → Markdown pulito Pipeline automatica che trasforma un PDF grezzo in Markdown strutturato e pronto per la suddivisione in chunk. Gestisce l'intero processo: validazione del PDF, estrazione del testo, pulizia strutturale e analisi della struttura del documento. ## Requisiti ### Python ``` pip install opendataloader-pdf pdfplumber ``` ### Java 11+ `opendataloader-pdf` richiede Java sul PATH. Se non è installato: ```bash # Ubuntu / Debian / WSL sudo apt install default-jdk # Verifica java -version ``` Download alternativo: https://adoptium.net/ --- ## Utilizzo Posiziona il PDF in `sources/.pdf`, poi: ```bash # Singolo documento python conversione/pipeline.py --stem # Tutti i PDF in sources/ python conversione/pipeline.py # Forza la riesecuzione (sovrascrive output esistente) python conversione/pipeline.py --stem --force ``` Il parametro `--stem` è il nome del file PDF senza estensione. Esempio: `sources/analisi1.pdf` → `--stem analisi1` --- ## Output Per ogni stem vengono prodotti tre file in `conversione//`: | File | Descrizione | |------|-------------| | `raw.md` | Markdown grezzo estratto dal PDF — **non modificare** | | `clean.md` | Markdown pulito e strutturato — input per il chunker | | `report.json` | Metriche complete di qualità della conversione | ### report.json Contiene tutto ciò che serve per valutare la conversione: statistiche trasformazioni, struttura rilevata, distribuzione lunghezze sezioni, anomalie e problemi residui con esempi. ```json { "stem": "dirittoprivato", "timestamp": "2026-04-16 15:41", "transforms": { "n_accenti_corretti": 0, "n_dotleader_rimossi": 0, "toc_rimosso": false, "n_sezioni_numerate": 63, "riduzione_pct": 1 }, "structure": { "livello_struttura": 3, "n_h1": 0, "n_h2": 6, "n_h3": 163, "lingua_rilevata": "it", "strategia_chunking": "h3_aware", "avvertenze": [] }, "distribution": { "min": 12, "p25": 312, "mediana": 681, "p75": 1197, "max": 6120 }, "anomalie": { "bare_headers": 0, "short_sections": 1, "long_sections": 39, "bare_headers_list": [], "short_sections_list": [...], "long_sections_list": [...] }, "residui": { "backtick": 0, "dotleader": 0, "url": 0, "immagini": 0, "backtick_esempi": [] } } ``` **`strategia_chunking`** indica come suddividere il documento in chunk: | Valore | Significato | |--------|-------------| | `h3_aware` | Documento ricco di sezioni `###` — usa i `###` come boundary | | `h2_paragraph_split` | Struttura parziale `##` — suddividi per paragrafo dentro ogni `##` | | `paragraph` | Nessuna gerarchia chiara — suddividi per paragrafo | | `sliding_window` | Testo piatto — usa finestra scorrevole | --- ## Validazione batch Dopo aver convertito uno o più documenti, esegui `validate.py` per ottenere una tabella di stato su tutti gli stem: ```bash python conversione/validate.py ``` Output di esempio: ``` stem h2 h3 strategia bare corte lunghe backtick dotlead url status ────────────────────────────────────────────────────────────────────────────────────────────── analisi1 13 279 h3_aware 0 36 151 10 0 0 ⚠️ dirittoprivato 6 163 h3_aware 0 1 39 0 0 0 ✅ nietzsche 4 303 h3_aware 6 104 100 0 0 0 ⚠️ ────────────────────────────────────────────────────────────────────────────────────────────── Totale: 3 ✅ 1 ⚠️ 2 ❌ 0 ``` **Legenda colonne:** | Colonna | Significato | Soglia warning | |---------|-------------|----------------| | `bare` | Header solo-numero senza corpo (`### 1.` vuoto) | ≥ 1 | | `corte` | Sezioni con corpo < 150 chars | informativo | | `lunghe` | Sezioni con corpo > 1500 chars | ≥ 80 | | `backtick` | Backtick `` ` `` residui nel testo | ≥ 1 | | `dotlead` | Dot-leader residui (`. . . .`) | ≥ 1 | **Stato:** - ✅ nessuna anomalia critica - ⚠️ anomalie presenti, documento processabile ma da verificare - ❌ struttura non rilevata (`livello_struttura = 0`) o > 50 backtick residui --- ## Cosa fa la pipeline La pipeline esegue quattro fasi in sequenza. ### Fase 1 — Validazione Verifica che il PDF esista, non sia vuoto, non sia protetto da password e contenga testo digitale estraibile. I PDF scansionati (immagini) non sono supportati. ### Fase 2 — Estrazione testo Usa `opendataloader-pdf` con l'algoritmo **XY-Cut++** per ricostruire il corretto ordine di lettura anche in documenti multi-colonna. Le immagini vengono ignorate completamente — il `clean.md` non contiene mai riferimenti a immagini. ### Fase 3 — Pulizia strutturale Serie di trasformazioni applicate al Markdown grezzo: | Trasformazione | Problema risolto | |----------------|-----------------| | Rimozione riferimenti immagini | Artefatti `![...]()` lasciati dal convertitore | | Fix accenti backtick LaTeX | `` `e``→`è`, ``puo` ``→`può`, ``sar`a``→`sarà` | | Rimozione dot-leader TOC | `- 1.1 Titolo . . . . . 42` (voci indice) | | Rimozione numerali romani pagina | `i`, `ii`, `iii` su riga isolata (footer LaTeX) | | Fix header + body concatenati | `### 11 TitoloCorpo testo...` → header + paragrafo separati | | Estrazione header Capitolo inline | `Capitolo 3: IL TITOLO` nel corpo → `## Capitolo 3: ...` | | Normalizzazione livelli header | `####`, `#####` → `###` (gerarchia uniforme a 3 livelli) | | Rimozione bold negli header | `## **Titolo**` → `## Titolo` | | Normalizzazione ALL-CAPS header | `## IL TITOLO` → `## Il titolo` | | Rimozione TOC | Blocchi indice/sommario rilevati per keyword | | ALL-CAPS standalone → header | Righe in maiuscolo isolate → `## Titolo` | | Sezioni numerate → header | `N. Titolo sezione` → `### N.` + corpo | | Sezioni con punto → header | `- N. Testo aphorismo...` → `### N.` + corpo | | Sezioni lista numerate → header | `- N Titolo Corpo testo...` → `### N. Titolo` + corpo | | Unione paragrafi spezzati | Paragrafi tagliati dal salto pagina PDF ricongiunti | | Normalizzazione whitespace | Spazi multipli ridotti a singoli | | Riduzione righe vuote | Tre o più righe vuote consecutive → due | | Rimozione URL watermark | `www.piattaforma.com`, `https://...` su riga isolata | | Rimozione header senza corpo | Sezioni vuote e header watermark scartati | > **Rilevamento automatico tipo documento**: se il documento contiene sezioni > "Esercizi" (libri di testo accademici), la conversione dei numeri di esercizio > in header viene disabilitata automaticamente. ### Fase 4 — Analisi struttura Rileva la gerarchia del documento (conteggio `#`/`##`/`###`), la lingua (italiano / inglese / sconosciuta), la lunghezza media delle sezioni e suggerisce la strategia di chunking ottimale. I risultati sono scritti in `structure_profile.json`. --- ## Tipi di documento supportati | Tipo | Esempi | Note | |------|--------|------| | Testo giuridico / accademico | Manuali, dispense, codici | Header numerati `N.` e `N.N` | | Filosofia / saggistica | Aforismi numerati, capitoli | Pattern `- N. testo` | | Matematica / LaTeX | Analisi, algebra, fisica | Fix accenti, TOC, numerali romani | | Testo generico strutturato | Qualsiasi PDF digitale | Paragrafi e header standard | **Non supportati**: PDF scansionati (solo immagini), PDF protetti da password. --- ## Log di esecuzione Durante l'esecuzione la pipeline stampa le statistiche di ogni trasformazione: ``` [3/4] Pulizia strutturale... ✅ Immagini rimosse: 0 Accenti corretti: 3701 Dot-leader rimossi: 53 Header concat fixati: 0 TOC rimosso: sì ALL-CAPS → ##: 14 Sezioni → ###: 279 Paragrafi uniti: 12998 Riduzione testo: 3% ``` Se un documento è già stato convertito, la pipeline lo salta automaticamente. Usa `--force` per rieseguire.