Files

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:

# Ubuntu / Debian / WSL
sudo apt install default-jdk

# Verifica
java -version

Download alternativo: https://adoptium.net/


Utilizzo

Posiziona il PDF in sources/<nome>.pdf, poi:

# Singolo documento
python conversione/ --stem <nome>

# Tutti i PDF in sources/
python conversione/

# Forza la riesecuzione (sovrascrive output esistente)
python conversione/ --stem <nome> --force

Il parametro --stem è il nome del file PDF senza estensione.
Esempio: sources/analisi1.pdf--stem analisi1


Output

Per ogni stem vengono prodotti quattro file in conversione/<stem>/:

File Descrizione
raw.md Markdown grezzo estratto dal PDF — non modificare
clean.md Markdown pulito e strutturato — input per il chunker
structure_profile.json Struttura rilevata e strategia di chunking consigliata
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.

{
  "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 per ottenere una tabella di stato su tutti gli stem:

# Tutti i documenti
python conversione/ validate

# Singolo documento con dettaglio penalità
python conversione/ validate <stem> --detail

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`asarà
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...
  ✅ Simboli PUA corretti:  0
     Immagini rimosse:      0
     Note rimosse:          12
     Accenti corretti:      3701
     Dot-leader rimossi:    53
     Header concat fixati:  0
     Header num. normaliz.: 8
     Articoli → ###:        0
     Ambienti matematici:   0
     Titoli header uniti:   4
     TOC rimosso:           sì
     Versi poesia riprist.: 0
     Header verso demotati: 0
     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.