spaCy per dati PII: riconoscimento e anonimizzazione dei testi

Quando si lavora con testi che contengono dati sensibili, una delle operazioni più comuni è l’identificazione e la gestione delle informazioni personalmente identificabili (in inglese, Personally Identifiable Information, abbreviato in PII). Si tratta di tutte quelle informazioni che permettono di risalire all’identità di una persona: nomi, indirizzi, numeri di telefono, indirizzi email, codici fiscali e molto altro.
In questo articolo vedremo come sfruttare spaCy, una delle librerie NLP più diffuse in Python, per individuare e gestire queste informazioni all’interno di un testo.
Cosa vedrai
- Cosa sono le PII
- Riconoscimento PII con spaCy
- Anonimizzare le entità rilevate
- Creare un riconoscitore personalizzato
- Visualizzare i risultati
- Risorse utili
Cosa sono le PII
Le PII includono qualsiasi informazione che, da sola o in combinazione con altri dati, può identificare univocamente una persona. Alcune categorie comuni sono:
- Dati anagrafici: nome, cognome, data di nascita
- Dati di contatto: numero di telefono, indirizzo email, indirizzo fisico
- Documenti di identità: codice fiscale, numero di passaporto, numero di carta d’identità
- Dati finanziari: IBAN, numero di carta di credito
- Identificatori digitali: indirizzo IP, username
Il rispetto delle normative come il GDPR impone alle organizzazioni di trattare questi dati con la massima attenzione: spesso è necessario anonimizzarli o pseudonimizzarli prima di poterli utilizzare in sistemi di analisi, log o dataset di addestramento.
Riconoscimento PII con spaCy
spaCy riconosce nativamente alcune entità che corrispondono a categorie PII, tramite il componente NER (Named Entity Recognition). Tra le entità riconoscibili troviamo:
| Label | Descrizione |
|---|---|
PERSON | Nomi di persone |
ORG | Organizzazioni e aziende |
GPE | Luoghi geopolitici (città, paesi) |
LOC | Luoghi fisici |
DATE | Date e periodi temporali |
MONEY | Valori monetari |
Per iniziare, installiamo spaCy e il modello per la lingua italiana (o inglese):
pip install spacy
python -m spacy download it_core_news_lg
# oppure per l'inglese:
python -m spacy download en_core_web_lg
Carichiamo il modello e analizziamo un testo di esempio:
import spacy
nlp = spacy.load("it_core_news_lg")
testo = """
Mario Rossi abita in Via Roma 12, Milano. Puoi contattarlo all'indirizzo mario.rossi@email.com
oppure al numero 333-1234567. Il suo codice fiscale è RSSMRA80A01F205X.
"""
doc = nlp(testo)
print("Entità rilevate:")
for ent in doc.ents:
print(f" Testo: {ent.text!r:30s} Label: {ent.label_}")
L’output mostrerà le entità riconosciute dal modello. Da notare che le entità come email, numeri di telefono e codice fiscale non vengono riconosciute nativamente da spaCy: occorre aggiungere dei matcher personalizzati.
Anonimizzare le entità rilevate
Una volta identificate le entità, è possibile sostituirle con segnaposti generici, mantenendo la struttura del testo ma rimuovendo le informazioni sensibili:
import spacy
nlp = spacy.load("it_core_news_lg")
def anonimizza_testo(testo: str, label_da_anonimizzare: list[str]) -> str:
"""Sostituisce le entità PII con un segnaposto generico."""
doc = nlp(testo)
testo_anonimizzato = testo
# Sostituisco dal fondo per non alterare gli indici
for ent in reversed(doc.ents):
if ent.label_ in label_da_anonimizzare:
segnaposto = f"[{ent.label_}]"
testo_anonimizzato = (
testo_anonimizzato[: ent.start_char]
+ segnaposto
+ testo_anonimizzato[ent.end_char :]
)
return testo_anonimizzato
testo = "Luca Ferrari lavora per Acme S.p.A. a Roma dal 2019."
label_pii = ["PERSON", "ORG", "GPE", "DATE"]
risultato = anonimizza_testo(testo, label_pii)
print(risultato)
# Output: "[PERSON] lavora per [ORG] a [GPE] dal [DATE]."
Creare un riconoscitore personalizzato
Per individuare entità come email, numeri di telefono o codici fiscali, possiamo usare il componente Matcher (per pattern linguistici) o il PhraseMatcher, oppure il più potente EntityRuler che supporta anche espressioni regolari tramite re.
Ecco come aggiungere un matcher basato su regex per rilevare indirizzi email e codici fiscali italiani:
import re
import spacy
from spacy.language import Language
from spacy.tokens import Span
nlp = spacy.load("it_core_news_lg")
PATTERN_PII = {
"EMAIL": r"[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}",
"TELEFONO": r"(?:\+39\s?)?(?:0\d{1,4}[\s\-]?\d{4,8}|3\d{2}[\s\-]?\d{6,7})",
"CODICE_FISCALE": r"\b[A-Z]{6}\d{2}[A-Z]\d{2}[A-Z]\d{3}[A-Z]\b",
"IBAN": r"\b[A-Z]{2}\d{2}[A-Z0-9]{11,27}\b",
}
@Language.component("pii_regex_detector")
def pii_regex_detector(doc):
"""Componente custom che aggiunge entità PII tramite regex."""
nuove_entita = list(doc.ents)
for label, pattern in PATTERN_PII.items():
for match in re.finditer(pattern, doc.text):
start_char, end_char = match.start(), match.end()
span = doc.char_span(start_char, end_char, label=label)
if span is not None:
nuove_entita.append(span)
# Filtro eventuali sovrapposizioni
doc.ents = spacy.util.filter_spans(nuove_entita)
return doc
# Aggiungo il componente alla pipeline dopo il NER nativo
nlp.add_pipe("pii_regex_detector", last=True)
testo = (
"Contatta Giulia Bianchi all'indirizzo giulia.bianchi@azienda.it "
"oppure al 333-9876543. Il suo CF è BNCGLI85M41H501Z."
)
doc = nlp(testo)
for ent in doc.ents:
print(f"{ent.label_:20s} → {ent.text!r}")
Output atteso:
PERSON → 'Giulia Bianchi'
EMAIL → 'giulia.bianchi@azienda.it'
TELEFONO → '333-9876543'
CODICE_FISCALE → 'BNCGLI85M41H501Z'
Visualizzare i risultati
spaCy include la libreria displaCy, che permette di visualizzare le entità rilevate direttamente nel browser o in un notebook Jupyter:
from spacy import displacy
# In un notebook Jupyter
displacy.render(doc, style="ent", jupyter=True)
# Oppure avvia un server locale
displacy.serve(doc, style="ent")
Il risultato è un’interfaccia visiva che evidenzia le entità con colori diversi a seconda della label assegnata: molto utile per verificare la qualità del riconoscimento e identificare eventuali falsi positivi o negativi.
Nota: spaCy da solo copre una parte delle entità PII. Per un sistema più completo, è possibile integrarlo con librerie dedicate come Microsoft Presidio, che combina spaCy con regole e validatori aggiuntivi per oltre 50 tipi di PII in più lingue.
















