Lab

Estrarre le singole pagine da un PDF senza siti web

13 min di lettura
Vista dall'alto di una persona alla scrivania che sfoglia pagine stampate sparse accanto a un raccoglitore aperto
Windows macOS Linux
Foto: Mikhail Nilov · Pexels · Licenza Pexels

Script Python · versione 1.0.0 · verificato

estrai_pagine.py

Script autonomo che gira solo sul tuo computer. Nessun upload, nessuna telemetria.

Formato
Script Python (.py)
Dimensione
2,8 KB
Python
3.9 o superiore
Licenza
MIT
Richiede
pypdf
Rete
Offline

Crea, rinomina o sposta file solo se lo chiedi tu (per esempio per il report o la quarantena). Il codice è leggibile riga per riga nel file scaricato.

Verifica integrità

SHA-256 di estrai_pagine.py

089b9f3f12f60519b794488b12071e5400525857e0c72e38d9574dd8d52d029a

Calcola lo SHA-256 del file scaricato e confrontalo con questo: Confronta hash · Come si verifica

Estrai una o più pagine da un PDF sul tuo PC con Python e pypdf, senza caricare documenti su siti web. Intervalli, una pagina per file, Windows/macOS/Linux.

Ti chiedono solo la pagina 4 di un contratto da quaranta pagine, o il modulo che sta in mezzo a un fascicolo. Cercando online trovi subito decine di siti che dividono i PDF gratis: carichi il file, scarichi la pagina. Nel frattempo il fascicolo intero, con tutto quello che nessuno ti ha chiesto, è uscito dal tuo computer.

Risposta breve: con Python e la libreria pypdf estrai le pagine che ti servono senza caricare nulla. Lo script di questo pezzo prende un PDF e un elenco come 1,3,5-7, poi scrive un file per ogni pagina oppure un solo file con quelle scelte. Ti servono un ambiente virtuale (venv) con pypdf e un comando.

Prima trovi il perché e i limiti, poi la preparazione e la logica dei numeri di pagina, dove si sbaglia più spesso. La parte pratica comincia da «Prepara la cartella e un PDF di prova».

Perché non conviene usare un sito per dividere i PDF

Un PDF lungo contiene quasi sempre più di ciò che devi mandare: codici fiscali, importi, indirizzi, a volte dati di altre persone. Caricarlo su un sito significa consegnarlo a un servizio di cui non controlli né per quanto tempo conserva i file né chi può accedervi. Questo non dimostra che quei siti ne facciano un uso scorretto: è un rischio teorico, non un fatto osservato. Il punto è che dall’esterno non lo puoi verificare. Secondo me, per un’operazione che sul tuo computer richiede pochi minuti, il compromesso non vale la comodità.

Mandare solo la pagina che serve fa un’altra cosa utile: riduce i dati che circolano, chiunque sia il destinatario.

Una controtesi onesta: per una pagina sola, una volta, può bastare il lettore PDF o la funzione di stampa su PDF del sistema, che in genere lavorano sul tuo computer. Se scegli quella strada, controlla il file ottenuto: testo selezionabile, segnalibri e campi dei moduli dipendono dal programma usato. Lo script conviene quando devi ripetere l’operazione, indicare intervalli o ottenere un file per pagina, e vuoi sapere esattamente che cosa succede, perché il codice è sotto i tuoi occhi.

Cosa fa lo script, cosa non fa e quando usa la rete

Cosa fa. Legge il PDF di partenza senza modificarlo e scrive nuovi file in una cartella (di default estratte). Se un file con lo stesso nome esiste già, si ferma invece di sovrascriverlo. Livello di rischio: writes-files.

Rete. Locale non vuol dire che non parta mai nulla: la connessione serve una volta sola, per scaricare pypdf con pip. Dopo l’installazione lo script non ne ha bisogno. Se vuoi controllarlo di persona, scollega il Wi-Fi prima di lanciarlo e guarda se funziona lo stesso.

Cosa non fa:

  • Non toglie nulla dalle pagine estratte: testo, immagini e firme restano come sono. Un rettangolo nero disegnato sopra un dato non lo elimina, e oscurare davvero un contenuto richiede un altro strumento, che questo articolo non tratta.
  • Non è uno strumento di pulizia dei metadati: controlla il file finale, come spiegato nella verifica.
  • Non apre i PDF protetti da password e non aggira nessuna protezione.
  • Non ripara i PDF danneggiati.
  • Non legge i numeri stampati sulle pagine: lavora sulla posizione fisica nel file.

Cosa riusi dal pezzo sull’unione dei PDF

Questo pezzo è il gemello di quello su come unire più PDF in locale: là metti insieme le pagine, qui le separi. Cambiano lo script e l’operazione, non il metodo. Se hai già seguito quel pezzo, hai la cartella di lavoro, il venv e pypdf installato: copia lo script nella stessa cartella e salta alla sezione sulla numerazione. Altrimenti le due sezioni successive ti portano allo stesso punto.

Prepara la cartella e un PDF di prova

Crea una cartella dove preferisci, per esempio dentro Documenti, e spostati al suo interno. I comandi sono uguali in PowerShell e nel terminale di macOS e Linux:

mkdir estrai-pagine
cd estrai-pagine

Per le prove usa un PDF fittizio, non un documento vero. Con un editor di testo (Word, Writer) crea un file di otto pagine in cui ogni pagina contiene una riga diversa («Questa è la pagina 1», «Questa è la pagina 2» e così via, con un’interruzione di pagina tra l’una e l’altra), poi esportalo in PDF con il nome fascicolo.pdf nella cartella. Quando estrarrai la pagina 4 vedrai subito se è davvero la 4. Se un giorno chiedi aiuto con uno screenshot, ti ringrazierai di non avere usato una carta d’identità.

Attiva il venv e installa pypdf

In Windows, da PowerShell:

python -m venv .venv
.venv\Scripts\Activate.ps1
python -m pip install pypdf
python -c "import pypdf; print(pypdf.__version__)"

Su macOS e Linux:

python3 -m venv .venv
source .venv/bin/activate
python3 -m pip install pypdf
python3 -c "import pypdf; print(pypdf.__version__)"

Se hai già un .venv dal pezzo sull’unione, il primo comando non serve. Quando l’attivazione riesce, il prompt comincia con (.venv). L’ultimo comando stampa un numero di versione: se lo vedi, l’import funziona. Annotalo, perché nomi e comportamenti delle funzioni possono cambiare tra una versione e l’altra. Si scrive python -m pip e non pip da solo perché così pip è quello dell’interprete del venv e non un altro installato altrove. Per approfondire ci sono le guide su ambienti virtuali e venv e su quando usare pip install.

⚠️ Attenzione — PowerShell può bloccare l’attivazione
Se compare un errore sull’esecuzione di script disabilitata, non serve cambiare le impostazioni di sistema. Chiama direttamente l’interprete del venv: .venv\Scripts\python.exe -m pip install pypdf, e più avanti .venv\Scripts\python.exe estrai_pagine.py ....

Come contare le pagine: da 1 per te, da 0 per Python

Tu dici «pagina 4». In pypdf la prima pagina è reader.pages[0], quindi la quarta è reader.pages[3]. L’errore classico è passare 4 come indice e ottenere la quinta pagina. Lo script ragiona come te: tu scrivi numeri da 1, e la funzione parse_pagine sottrae uno prima di toccare pypdf.

Negli intervalli gli estremi sono inclusi: 5-7 significa 5, 6 e 7. In Python range(4, 7) produce 4, 5 e 6, cioè gli indici delle pagine 5, 6 e 7, ed è quello che il codice usa.

Cosa scriviIndici usati da pypdfPagine estratte
43la quarta
1,3,5-70, 2, 4, 5, 61, 3, 5, 6, 7
2-41, 2, 32, 3, 4
7-5nessunoerrore: intervallo invertito
9 (PDF di 8 pagine)nessunoerrore: fuori range

Un caso limite cambia la decisione: il numero stampato sul foglio e la posizione nel file possono non coincidere. Con una copertina, un indice con numeri romani o pagine non numerate, quella che porta scritto «4» può essere la sesta del PDF. Lo script usa la posizione fisica, la stessa che mostra il contatore del lettore PDF («6 di 40»). Se il numero che ti hanno indicato è quello stampato, apri il file e leggi il contatore prima di lanciare il comando.

Lo script completo, pezzo per pezzo

Salva questo codice come estrai_pagine.py nella cartella di lavoro, oppure scaricalo dal pulsante di download della pagina.

import argparse
import sys
from pathlib import Path

from pypdf import PdfReader, PdfWriter
from pypdf.errors import PdfReadError


def leggi_numero(testo):
    try:
        return int(testo)
    except ValueError:
        raise ValueError(f"'{testo}' non è un numero di pagina") from None


def parse_pagine(elenco, totale):
    """Trasforma '1,3,5-7' in indici da 0: [0, 2, 4, 5, 6]."""
    indici = []
    for parte in elenco.split(","):
        parte = parte.strip()
        if not parte:
            continue
        if "-" in parte:
            da, a = parte.split("-", 1)
            inizio, fine = leggi_numero(da), leggi_numero(a)
        else:
            inizio = fine = leggi_numero(parte)
        if inizio > fine:
            raise ValueError(f"intervallo invertito: '{parte}'")
        if inizio < 1 or fine > totale:
            raise ValueError(f"'{parte}' è fuori range: il PDF ha {totale} pagine")
        indici.extend(range(inizio - 1, fine))
    if not indici:
        raise ValueError("nessuna pagina indicata")
    return indici


def salva(writer, destinazione):
    if destinazione.exists():
        sys.exit(f"Errore: {destinazione} esiste già. Scegli un'altra cartella con -o.")
    with open(destinazione, "wb") as f:
        writer.write(f)
    print(f"Creato: {destinazione}")


def main():
    ap = argparse.ArgumentParser(description="Estrae pagine da un PDF, in locale.")
    ap.add_argument("input", type=Path, help="il PDF di partenza")
    ap.add_argument("-p", "--pagine", required=True,
                    help="pagine da estrarre, contate da 1: per esempio 1,3,5-7")
    ap.add_argument("--unisci", action="store_true",
                    help="un solo file con tutte le pagine scelte")
    ap.add_argument("-o", "--output-dir", type=Path, default=Path("estratte"),
                    help="cartella di destinazione (default: estratte)")
    args = ap.parse_args()

    if not args.input.is_file():
        sys.exit(f"Errore: non trovo il file {args.input}")
    try:
        reader = PdfReader(args.input)
    except PdfReadError as e:
        sys.exit(f"Errore: il PDF non si legge ({e})")
    if reader.is_encrypted:
        sys.exit("Errore: il PDF è protetto da password. Lo script non lo apre.")
    try:
        indici = parse_pagine(args.pagine, len(reader.pages))
    except ValueError as e:
        sys.exit(f"Errore: {e}")

    args.output_dir.mkdir(parents=True, exist_ok=True)
    if args.unisci:
        writer = PdfWriter()
        for i in indici:
            writer.add_page(reader.pages[i])
        salva(writer, args.output_dir / f"{args.input.stem}_estratte.pdf")
    else:
        for i in indici:
            writer = PdfWriter()
            writer.add_page(reader.pages[i])
            salva(writer, args.output_dir / f"pagina_{i + 1:03d}.pdf")


if __name__ == "__main__":
    main()

I passaggi con pypdf, uno per uno:

  1. PdfReader(args.input) apre il PDF di partenza in lettura. Non lo modifica. Se il file non è un PDF valido, solleva PdfReadError, che lo script trasforma in un messaggio chiaro.
  2. reader.is_encrypted dice se il PDF è cifrato. Lo script si ferma subito, prima di contare le pagine.
  3. len(reader.pages) è il numero totale di pagine. Serve a parse_pagine per riconoscere i numeri fuori range.
  4. reader.pages[i] è la pagina in posizione i, contata da 0.
  5. PdfWriter() crea un PDF nuovo e vuoto.
  6. writer.add_page(pagina) copia la pagina nel nuovo PDF. Aggiungendone più di una, restano nell’ordine in cui le aggiungi.
  7. writer.write(f) scrive il PDF nel file aperto con open(destinazione, "wb"). La b significa scrittura binaria: un PDF non è un file di testo.

La funzione salva si rifiuta di sovrascrivere, e sys.exit("...") stampa il messaggio e chiude lo script con un codice di errore. Le chiamate sono quelle della documentazione di pypdf: controllale sulla versione che hai installato, perché possono cambiare. Per capire come lo script legge gli argomenti c’è la guida ad argparse in Python.

I flag uno per uno e tre ricette

  • input (posizionale): il PDF di partenza. Se il percorso ha spazi, mettilo tra virgolette. Il file viene solo letto.
  • -p / --pagine: obbligatorio. L’elenco delle pagine, contate da 1, con virgole e intervalli.
  • --unisci: senza questo flag ottieni un file per pagina, chiamato pagina_004.pdf (il numero è quello della pagina nel PDF originale). Con il flag ottieni un solo file, nome-originale_estratte.pdf, con le pagine nell’ordine in cui le hai scritte: -p 3,1 mette prima la 3 e poi la 1.
  • -o / --output-dir: la cartella di destinazione. Se non esiste viene creata; se non la indichi si chiama estratte.

Le ricette sono per Windows; su macOS e Linux sostituisci python con python3. Gli output sono un esempio ipotetico, con file fittizi.

Una pagina sola:

python estrai_pagine.py fascicolo.pdf -p 4
Creato: estratte\pagina_004.pdf

Un intervallo in un solo file:

python estrai_pagine.py fascicolo.pdf -p 5-7 --unisci
Creato: estratte\fascicolo_estratte.pdf

Tutte le pagine, una per file (sostituisci 8 con il numero di pagine del tuo PDF):

python estrai_pagine.py fascicolo.pdf -p 1-8 -o singole
Creato: singole\pagina_001.pdf
Creato: singole\pagina_002.pdf
...

Esegui lo script e verifica il risultato

Lo script ha già fatto il lavoro nelle ricette qui sopra. Ora devi controllare che il risultato sia quello che volevi, e il controllo è la parte che conta.

  1. Apri il file creato nel lettore PDF e guarda il contatore. Con pagina_004.pdf deve dire una pagina sola. Con il PDF di prova, la riga sulla pagina deve essere «Questa è la pagina 4». Con un documento vero, confronta con l’originale un elemento riconoscibile: l’intestazione, una firma, un titolo.
  2. Controlla da terminale quante pagine ha il file e che metadati porta:
python -c "from pypdf import PdfReader; r = PdfReader('estratte/pagina_004.pdf'); print(len(r.pages), r.metadata)"
1 {'/Producer': 'pypdf'}

Esempio ipotetico: il contenuto dei metadati dipende dal PDF di partenza e dalla versione di pypdf. Non dare per scontato che il file nuovo non contenga informazioni sull’autore o sul programma che l’ha creato: stampale e leggile. Per il tema dei metadati nelle foto c’è il lab su come rimuovere i metadati EXIF.

  1. Controlla che il PDF di partenza sia intatto: lo script lo apre soltanto in lettura.
  2. Prima di inviare, riapri il file che stai per allegare. L’errore più umano è allegare per sbaglio il fascicolo intero.

Le pagine estratte restano identiche a quelle dell’originale: se in un piè di pagina c’è il nome di un’altra persona, c’è ancora.

Errori comuni e cosa fare

Pagina fuori range. Come appare: Errore: '9' è fuori range: il PDF ha 8 pagine. Perché succede: hai indicato una pagina che non esiste, magari contando dal numero stampato. Il fix: apri il PDF, leggi il contatore e correggi l’elenco.

PDF protetto da password. Come appare: Errore: il PDF è protetto da password. Lo script non lo apre. Perché succede: pypdf riconosce la cifratura e lo script si ferma per scelta. Il fix: se il documento è tuo e conosci la password, usa un lettore PDF che ti permetta di salvarne una copia senza protezione. Se non sei tu a poterlo aprire, lo script non è lo strumento.

Percorso con spazi. Come appare: error: unrecognized arguments: casa.pdf. Perché succede: il terminale ha spezzato Contratto casa.pdf in due argomenti. Il fix: metti il percorso tra virgolette, "Contratto casa.pdf".

pip fuori dal venv. Come appare: ModuleNotFoundError: No module named 'pypdf'. Perché succede: pypdf è stato installato in un altro ambiente, oppure il venv non è attivo. Il fix: verifica che il prompt mostri (.venv), riattiva il venv e rilancia python -m pip install pypdf.

Pagina sbagliata di una posizione. Come appare: nel file c’è la pagina accanto a quella cercata. Perché succede: hai usato il numero stampato oppure hai contato da 0. Il fix: usa il contatore del lettore PDF e numera da 1.

Domande Frequenti (FAQ)

Cosa succede con i PDF protetti da password?

Lo script si ferma e non tenta di aprirli. In pypdf esiste un metodo per decifrare un file con una password nota, ma qui non è usato per scelta, per non maneggiare password sulla riga di comando. Alcuni tipi di cifratura possono richiedere pacchetti aggiuntivi: controlla la documentazione ufficiale di pypdf per la tua versione.

L’estrazione cancella metadati o dati sensibili?

I dati nelle pagine restano: nome, codici, firme, tutto ciò che si vede e anche ciò che non si vede ma è nel contenuto. Per i metadati dipende dal file, e il comando di verifica ti mostra che cosa c’è. Pulire o oscurare davvero richiede un passaggio dedicato.

Posso estrarre da più PDF in una volta?

Lo script ne tratta uno per volta. Per più file lo lanci una volta per ciascuno, meglio con una cartella di destinazione diversa (-o), perché i nomi pagina_001.pdf potrebbero coincidere.

Posso cambiare l’ordine delle pagine?

Sì, con --unisci: le pagine finiscono nel file nell’ordine in cui le scrivi, quindi -p 3,1 produce un file con la 3 e poi la 1. Senza il flag l’ordine non conta, perché ogni pagina ha il suo file.

Funziona su Windows, macOS e Linux?

Il codice non usa nulla di specifico di un sistema operativo. Cambiano il comando dell’interprete (python su Windows, python3 su macOS e Linux) e il modo di attivare il venv.

Prima di inviare la pagina, e cosa leggere dopo

Estrarre una pagina riduce quello che mandi, non cambia ciò che quella pagina contiene. Prima di allegarla, rileggila come la leggerebbe chi la riceve.

Per il pezzo gemello, unire più PDF in locale.

Alex Lunalbi

Alex Lunalbi

Security & privacy

Dona su PayPal

Scrivo di sicurezza digitale pratica e codice IA. Su ai riparo ogni procedura è verificata su macchine reali.

Tag
  • python,
  • pdf,
  • privacy,
  • venv,
  • script