deutsch-deid: PII detection, masking & anonymization for German EdTech applications.
Project description
deutsch-deid — Erkennung & Anonymisierung von personenbezogenen Daten auf Deutsch
Erkennung, Maskierung und Anonymisierung personenbezogener Daten (PII) in deutschen Texten und Dokumenten.
Entwickelt für EdTech-Anwendungen und DSGVO-Compliance.
Was ist deutsch-deid?
deutsch-deid ist eine Python-Bibliothek zur Erkennung und Anonymisierung personenbezogener Daten in deutschen Texten und Dokumenten (.pdf, .docx, .txt). Sie kombiniert:
- Angepasste deutsche Regex-Erkenner — handoptimierte Muster für deutsche Identifikatoren (PLZ, Telefonnummern, SVNR, Steuer-ID, USt-IdNr, …)
- spaCy German NER (
de_core_news_lg) — neuronale Eigennamenerkennung für Personen und Orte - Algorithmische Validierung — ISO 7064 MOD 11,10 für individuelle Steuer-ID und USt-IdNr; SVN-Modular-Check für die SVNR
- Kontextbewusstes Scoring — satzgebundene Schlüsselwortfenster erhöhen oder verringern die Konfidenz vor der Anonymisierung
Anwendungsfälle: Anonymisierung von Schülerakten, Anonymisierung von Lernmanagementsystem-Daten, Bereinigung von Anmeldungsformularen, DSGVO-Datensparsamkeits-Pipelines, Schutz personenbezogener Daten von Lehrern und Schülern.
Hauptfunktionen
| Funktion | Details |
|---|---|
| 11 Entitätstypen | Kern-PII-Abdeckung — Personen, Orte, Datum, Uhrzeit, Kontaktdaten, Netzwerkdaten und deutsche Ausweisdokumente |
| 3 Schutzmodi | anonymize (realistische synthetische Ersatzwerte) · tag ([PERSON]) · i_tag ([PERSON_1]) |
| Dokumentenunterstützung | Liest .pdf (pypdf), .docx (python-docx) und .txt nativ |
| PDF-Normalisierung | Repariert automatisch pypdf-Extraktionsartefakte (doppelte Leerzeichen, Wort-pro-Zeile-Streuung) |
| Algorithmische Validierung | ISO 7064 MOD 11,10 für Steuer-ID & USt-IdNr · SVN-Modular-Check für SVNR |
| Kontextbewusstes Scoring | Satzgebundene Schlüsselwortfenster erhöhen oder verringern Konfidenzwerte |
| Vokabularebenen | Unterscheidung zwischen starken und schwachen Schlüsselwörtern — teilweise Verstärkung bei mehrdeutigem Kontext |
| Negativer Kontext | Widersprechende Schlüsselwörter reduzieren den Score vor der Schwellwertfilterung |
| Entitätsfilterung | keep-Allowlist oder ignore-Denylist pro Aufruf |
| Eigene Muster | Eigene Regex-Muster mit optionalen Kontextwörtern und Fake-Wert-Pools einbinden |
| DSGVO-bereit | Für deutsche EdTech-Datenpipelines und Schülerdatenschutz-Anforderungen ausgelegt |
Installation
pip install deutsch-deid
Laden Sie das spaCy-Modell herunter (erforderlich für die Erkennung von PERSON und LOCATION):
python -m spacy download de_core_news_lg
Für die Dokumentenverarbeitung werden optionale Abhängigkeiten benötigt:
pip install pypdf # PDF-Unterstützung
pip install python-docx # DOCX-Unterstützung
Schnellstart
from deutsch_deid import analyze, guard
text = (
"Schüler: Anna Richter, Klasse 9A. "
"E-Mail: a.richter@gymnasium-berlin.de. "
"Telefon: +49 162 55512345. "
"Sozialversicherungsnummer: 12 150780 J 009."
)
# ── PII erkennen ──────────────────────────────────────────────────
findings = analyze.text(text)
for f in findings:
print(f"[{f['type']}] {text[f['start']:f['end']]} (Score: {f['score']})")
# [PERSON] Anna Richter (Score: 0.85)
# [EMAIL_ADDRESS] a.richter@gymnasium-berlin.de (Score: 0.95)
# [PHONE_NUMBER] +49 162 55512345 (Score: 0.75)
# [SVNR] 12 150780 J 009 (Score: 0.90)
# ── Anonymisieren (Standardmodus) ─────────────────────────────────
result = guard.text(text)
print(result["guarded_text"])
# "Schüler: Lukas Bauer, Klasse 9A. E-Mail: l.bauer@beispiel.de.
# Telefon: +49 151 87654321. Sozialversicherungsnummer: 65 230561 M 013."
# ── Tag-Modus ─────────────────────────────────────────────────────
print(guard.text(text, config={"mode": "tag"})["guarded_text"])
# "Schüler: [PERSON], Klasse 9A. E-Mail: [EMAIL_ADDRESS].
# Telefon: [PHONE_NUMBER]. Sozialversicherungsnummer: [SVNR]."
# ── Indizierter Tag-Modus ─────────────────────────────────────────
print(guard.text(text, config={"mode": "i_tag"})["guarded_text"])
# "Schüler: [PERSON_1], Klasse 9A. E-Mail: [EMAIL_ADDRESS_1].
# Telefon: [PHONE_NUMBER_1]. Sozialversicherungsnummer: [SVNR_1]."
Dokumentenverarbeitung
Dateien direkt verarbeiten — Textextraktion und PII-Analyse in einem Aufruf:
from deutsch_deid import analyze, guard
# Datei analysieren
findings = analyze.doc("schuelerakte.pdf")
findings = analyze.doc("anmeldeformular.docx")
findings = analyze.doc("klassennotizbuch.txt")
# Datei anonymisieren
result = guard.doc("schuelerakte.pdf")
print(result["guarded_text"]) # bereinigter, anonymisierter Text
print(result["findings"]) # Liste der erkannten PII-Spans
# Alle Konfigurationsoptionen funktionieren genauso wie bei .text()
result = guard.doc("anmeldeformular.docx", config={
"mode": "tag",
"score_threshold": 0.6,
"set_entities": {"keep": ["PERSON", "SVNR", "STEUER_ID"]},
})
Unterstützte Formate:
| Format | Leser | Hinweise |
|---|---|---|
.txt |
eingebautes open() |
UTF-8 |
.pdf |
pypdf |
Alle Seiten zusammengeführt; Abstandsartefakte werden automatisch normalisiert |
.docx |
python-docx |
Alle Absätze zusammengeführt |
Jede andere Erweiterung löst einen UnsupportedFormatError aus, bevor die Dateiexistenz geprüft wird.
Unterstützte Entitätstypen
| Entität | Beschreibung | Erkenner | Validierung |
|---|---|---|---|
PERSON |
Personennamen | spaCy NER (de_core_news_lg) |
— |
LOCATION |
Städte, Adressen, Regionen | spaCy NER (de_core_news_lg) |
— |
DATE |
Datumsangaben (numerisch und mit deutschen Monatsnamen) | Regex | — |
TIME |
Uhrzeiten (12h / 24h / „Uhr"-Format) | Regex | — |
PHONE_NUMBER |
Deutsche Mobil- und Festnetznummern, EU-International | Regex | — |
EMAIL_ADDRESS |
E-Mail-Adressen | Regex | — |
URL |
HTTP/HTTPS/FTP und schemalose www.*-Links |
Regex | — |
ZIPCODE |
Deutsche 5-stellige Postleitzahlen | Regex | — |
IP_ADDRESS |
IPv4- und IPv6-Adressen | Regex | — |
SVNR |
Sozialversicherungsnummer — Struktur 2+6+1+2+1 | Regex | SVN-Modular-Check |
STEUER_ID |
USt-IdNr (DE+9d), Steuernummer (Schrägstrichformat), individuelle TIN (11d) |
Regex | ISO 7064 MOD 11,10 |
Schutzmodi
| Modus | Verhalten | Ausgabebeispiel |
|---|---|---|
anonymize (Standard) |
Ersetzt jede Entität durch einen realistischen synthetischen deutschen Wert | Lukas Bauer, DE876543219, 12 150780 J 009 |
tag |
Ersetzt durch [ENTITÄTSTYP] |
[PERSON], [SVNR], [STEUER_ID] |
i_tag |
Ersetzt durch [ENTITÄTSTYP_N] — gleicher Entitätstyp erhält gleichen Index |
[PERSON_1] … [PERSON_2] |
Konfiguration
Alle Optionen werden über ein einzelnes config-Dictionary übergeben:
# Allowlist — nur diese Entitätstypen erkennen
config = {"set_entities": {"keep": ["PERSON", "SVNR", "STEUER_ID"]}}
# Denylist — alles außer diesen erkennen
config = {"set_entities": {"ignore": ["DATE", "TIME"]}}
# Vollständiges Konfigurationsbeispiel
config = {
"set_entities": {"keep": ["PERSON", "SVNR", "STEUER_ID"]},
# Minimale Konfidenz für einen Fund
"score_threshold": 0.5,
# Schutzmodus
"mode": "anonymize", # "anonymize" | "tag" | "i_tag"
# Eigene Muster (siehe unten)
"custom_patterns": [...],
}
Eigene Muster
from deutsch_deid import analyze, guard, custom_pattern
schueler_id = custom_pattern(
name="SCHUELER_ID",
regex=r"STU-\d{4}",
score=0.9,
context=["schüler", "student", "matrikelnummer"], # Nahe Wörter erhöhen den Score
anonymize_list=["STU-9999", "STU-8888"], # Fake-Pool für den Anonymisierungsmodus
)
findings = analyze.text("Schüler STU-1234 hat Zugriff.", config={"custom_patterns": [schueler_id]})
guarded = guard.text("Schüler STU-1234 hat Zugriff.", config={"custom_patterns": [schueler_id]})
print(guarded["guarded_text"])
# "Schüler STU-9999 hat Zugriff."
Scoring & Konfidenz
Jeder Fund trägt einen score zwischen 0 und 1. Die Scores werden durch ein Vier-Stufen-System bestimmt:
| Stufe | Bedingung | Beispiel-Score |
|---|---|---|
base |
Nur Regex-Treffer, keine weiteren Hinweise | 0,30 – 0,85 |
with_context |
Ein relevantes Schlüsselwort erscheint im selben Satz | bis zu 0,92 |
validated |
Algorithmische Prüfsumme bestanden (SVN-Check / ISO 7064 MOD 11,10) | 0,70 – 0,92 |
high_confidence |
Validierung und Kontextschlüsselwort vorhanden | 0,90 – 0,92 |
Das Context-Scoring ist satzbewusst — Kontextschlüsselwörter aus anderen Sätzen beeinflussen den Score nicht. Negative Kontextschlüsselwörter reduzieren die Konfidenz aktiv.
Mit score_threshold können Ergebnisse mit niedriger Konfidenz vor der Anonymisierung gefiltert werden.
Paketstruktur
deutsch_deid/
├── types.py — Kerndatenstrukturen (RecognizerResult, Pattern, …)
├── analysis/
│ ├── analyzer.py — PII-Analyse-Engine (GuardAnalyzer)
│ ├── context_awareness.py — satzbewusstes Keyword-Scoring (ContextEnhancer)
│ └── overlap_resolver.py — Span-Deduplizierung & Zusammenführung
├── anonymization/
│ ├── engine.py — zustandsloser Anonymisierungs-Dispatcher (GuardEngine)
│ └── fake_data.py — synthetische deutsche PII-Pools
├── recognizers/
│ ├── base.py — EntityRecognizer / PatternRecognizer Basisklassen
│ ├── contact.py — PHONE_NUMBER, EMAIL_ADDRESS, URL
│ ├── datetime.py — DATE, TIME
│ ├── device.py — IP_ADDRESS
│ ├── location.py — ZIPCODE
│ ├── social.py — SVNR (Sozialversicherungsnummer)
│ ├── tax.py — STEUER_ID (USt-IdNr, Steuernummer, individuelle TIN)
│ └── spacy_recognizer.py — NER-Erkenner (PERSON, LOCATION)
├── processors/
│ ├── text_processor.py — Analyse-/Schutz-Pipelines für Klartext
│ └── doc_processor.py — Dateilesen (.pdf / .docx / .txt) + Normalisierung
├── config/
│ ├── entities.py — ALL_DE_ENTITY_TYPES-Liste
│ └── scoring.py — EntityScoreProfile pro Entitätstyp
└── patterns/
├── german_keywords.py — Deutsche Monatsnamen und Schlüsselwortlisten
└── german_patterns.py — Alle Regex-Muster
Die öffentliche Schnittstelle wird über deutsch_deid/__init__.py bereitgestellt:
from deutsch_deid import analyze, guard, custom_pattern, ALL_DE_ENTITY_TYPES
Datenschutz & Compliance
| Standard | Unterstützung durch diese Bibliothek |
|---|---|
| DSGVO / GDPR | De-identifiziert personenbezogene Daten vor Speicherung oder Übertragung; unterstützt Datensparsamkeitspflichten |
| Schülerdatenschutz | Bietet eine technische Kontrollschicht für die Pseudonymisierung von Schüler- und Lernenddaten in EdTech-Pipelines |
| Mensch im Loop | Automatische Erkennung ist probabilistisch — bei kritischen Datensätzen immer eine manuelle Überprüfung des anonymisierten Outputs einplanen |
Diese Bibliothek ist ein technisches Werkzeug, keine rechtliche Garantie. Die gesamte Pipeline-Architektur, Zugriffskontrollen und Data-Governance-Richtlinien müssen die geltenden regulatorischen Anforderungen erfüllen.
Interaktiver Schnellstart
Das Notebook examples/quickstart.ipynb behandelt:
- Text- und Dokumentenanalyse mit allen 11 Entitätstypen
- SVNR-Erkennung (Sozialversicherungsnummer) & Validierung
- STEUER_ID — alle drei Varianten (USt-IdNr, Steuernummer, individuelle TIN)
- Alle drei Schutzmodi (
anonymize,tag,i_tag) - Eigene Muster mit Anonymisierungs-Pools
- Entitätsfilterung und Score-Schwellenwerte
- Vollständiges Beispiel mit deutschem Schülerausweis
Lizenz
MIT-Lizenz — siehe LICENSE für Details.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file deutsch_deid-1.0.0.tar.gz.
File metadata
- Download URL: deutsch_deid-1.0.0.tar.gz
- Upload date:
- Size: 50.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
79bfafb9e8c554f89170415313c26d6d089a7efbacfb78ee8b6a9e288724b8a8
|
|
| MD5 |
42144fb23d06b415147e7ffc776ce126
|
|
| BLAKE2b-256 |
72572dadbbbf8eb72fdeadc549c1a0d2ad323e56038ed4228698388c230bdbba
|
Provenance
The following attestation bundles were made for deutsch_deid-1.0.0.tar.gz:
Publisher:
publish.yml on wd-core/deutsch-deid
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
deutsch_deid-1.0.0.tar.gz -
Subject digest:
79bfafb9e8c554f89170415313c26d6d089a7efbacfb78ee8b6a9e288724b8a8 - Sigstore transparency entry: 1327456613
- Sigstore integration time:
-
Permalink:
wd-core/deutsch-deid@92064fddee4b9988421a9360b3a492adb78e2203 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/wd-core
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@92064fddee4b9988421a9360b3a492adb78e2203 -
Trigger Event:
push
-
Statement type:
File details
Details for the file deutsch_deid-1.0.0-py3-none-any.whl.
File metadata
- Download URL: deutsch_deid-1.0.0-py3-none-any.whl
- Upload date:
- Size: 52.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8a77ab59b01a9ea4751859de800de04081901c46ee154be737059073fa051a22
|
|
| MD5 |
7e2ed4b30292296cbc156b9815826cba
|
|
| BLAKE2b-256 |
f7769a247c71c229b00749c6652720ecccc222cff71cff2cbb19a998680a90db
|
Provenance
The following attestation bundles were made for deutsch_deid-1.0.0-py3-none-any.whl:
Publisher:
publish.yml on wd-core/deutsch-deid
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
deutsch_deid-1.0.0-py3-none-any.whl -
Subject digest:
8a77ab59b01a9ea4751859de800de04081901c46ee154be737059073fa051a22 - Sigstore transparency entry: 1327457050
- Sigstore integration time:
-
Permalink:
wd-core/deutsch-deid@92064fddee4b9988421a9360b3a492adb78e2203 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/wd-core
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@92064fddee4b9988421a9360b3a492adb78e2203 -
Trigger Event:
push
-
Statement type: