💡 Voll funktionsfähiges Beispiel auf GitHub verfügbar:
sanitize-office-document-pii-python
Die Daten, die niemand prüft, bevor er auf Senden klickt
Ein vierteljährlicher Vorstandbericht wird an einen externen Prüfer gesendet. Der Text ist makellos; drei Überprüfungszyklen haben das sichergestellt. Die Datei selbst erzählt eine andere Geschichte. Ihre Eigenschaften nennen noch immer den Analysten, der sie erstellt hat, den Manager, der sie überarbeitet hat, die Unternehmens‑Tochtergesellschaft, die die Vorlage besitzt, einen LastPrinted‑Zeitstempel von der Nacht vor der Frist und eine SharePoint‑Genehmiger‑ID aus dem internen Freigabe‑Workflow. Keines davon erscheint auf einer Seite. Alles reist mit der Datei mit.
Die Entfernung von PII ist ein GroupDocs.Metadata‑Workflow für Python via .NET, der diese identitätsbezogenen Eigenschaften aus Word-, Excel‑ und PowerPoint‑Dateien programmgesteuert entfernt. Dieser Artikel vergleicht die drei von der API angebotenen Ansätze: tag‑gesteuerte Entfernung für Identitätsfelder, namensbasierte Musterentfernung für Eigenschaftsfamilien wie Kommentare und Revisionen sowie den Einmalaufruf sanitize(), der alles löscht. Außerdem sehen Sie den Schritt, den die meisten Bereinigungsskripte überspringen – einen Verifizierungsscan, der beweist, dass die Bereinigung tatsächlich gehalten wurde.
Warum Metadaten‑PII eine eigene Pipeline verdient
Werkzeuge zur Inhaltsprüfung prüfen, was Menschen lesen. Sie prüfen nicht, was Dateisysteme speichern, und genau diese Lücke verursacht Compliance‑Vorfälle. Eine DSGVO‑Anfrage umfasst personenbezogene Daten in den Feldern Author und Manager genauso wie Daten im Text. Rechtliche Discovery liest Revisionszähler und Bearbeitungszeit‑Summen, um nachzuvollziehen, wie lange ein Positionspapier verhandelt wurde. Ausschreibungsprüfer können Ihre Organisationsstruktur aus SharePoint‑Workflow‑Eigenschaften ableiten, und die Kommentar‑Felder einer Pressemitteilung bewahren Reviewer‑Namen neben Entwurfs‑Anmerkungen. Jeder dieser Punkte ist ein Befund. Keiner von ihnen ist im Dokumentenkörper sichtbar.
Voraussetzungen
Bevor Sie beginnen, stellen Sie sicher, dass Sie haben:
- Python 3 mit pip
- GroupDocs.Metadata für Python via .NET, im Beispiel‑Repository auf Version 26.5 festgelegt
- Eine Office‑Datei mit echten Eigenschaften zum Üben
Installation
pip install groupdocs-metadata-net==26.5
Das companion repository liefert ein Beispiel‑DOCX und führt jedes untenstehende Snippet als behauptete Pipeline aus.
Methode 1: Tag‑gesteuerte Identitätsentfernung
Die vier sensibelsten Felder, Author, LastSavedBy, Manager und Company, haben in den verschiedenen Office‑Formaten unterschiedliche interne Namen. Das Tag‑System löst das: Anstatt Eigenschaften zu benennen, fragt das Prädikat nach allem, das als Person oder Unternehmen getaggt ist.
# Match identity properties by meaning, not by format-specific name
with Metadata("board-report.docx") as metadata:
removed = metadata.remove_properties(lambda p:
Tags.person.creator in list(p.tags) # Author, LastSavedBy
or Tags.person.editor in list(p.tags)
or Tags.person.manager in list(p.tags)
or Tags.corporate.company in list(p.tags))
metadata.save("board-report-clean.docx")
print(f"{removed} identity properties removed")
Wichtige Punkte:
- Formatunabhängigkeit: Das gleiche Lambda bereinigt DOCX, XLSX und PPTX, weil Tags nach Rolle klassifizieren.
- Zählbares Ergebnis:
remove_propertiesgibt zurück, wie viele Eigenschaften zutrafen, was in Ihr Audit‑Log gehört. - Kopiersemantik: Das Speichern unter einem neuen Pfad behält das Original für Ihre Unterlagen.
💡 Tipp: Dieser Durchlauf bewahrt Title, Subject und andere beschreibende Felder, sodass die Datei für Suche und DMS‑Indexierung freundlich bleibt.
Methode 2: Namens‑Muster‑Entfernung für Eigenschaftsfamilien
Tags decken klassifizierte Konzepte ab. Ganze Familien von leaky‑Feldern liegen außerhalb dieser Klassifizierung: Kommentar‑Eigenschaften, Revisionszähler, SharePoint‑Workflow‑Stempel. Für diese wird der Eigenschaftsname selbst gematcht.
# Comment fields often live in custom properties the tag system
# does not classify, so match them by name substring
with Metadata("board-report.docx") as metadata:
removed = metadata.remove_properties(lambda p:
p.name is not None and (
"Comment" in p.name
or "Reviewer" in p.name
or "Reviewed" in p.name))
metadata.save("board-report-no-comments.docx")
Die gleiche Form behandelt die anderen beiden Familien; nur die Teilstring‑Liste ändert sich:
| Familie | Zu matchende Teilstrings |
|---|---|
| Revisionsverlauf | Revision, TrackedChange, LastPrinted, TotalEditingTime, EditTime |
| Server / Workflow | Server, Workflow, Approver, ContentType, Template |
Dies tauscht Präzision gegen Reichweite: "Comment" fängt auch Comments und CommentCount ab, was normalerweise das Ziel eines Bereinigungsdurchlaufs ist. Breite Teilstrings können auch harmlose Vorlagenfelder treffen, daher sollten Sie die zurückgegebene Anzahl gegen Erwartungen prüfen.
💡 Tipp: Führen Sie jede Familie als eigenen Durchlauf aus, wenn Ihr Audit‑Log pro‑Kategorie‑Zählungen benötigt; fassen Sie die Teilstrings zu einem Prädikat zusammen, wenn das nicht nötig ist.
Methode 3: Der Einmalaufruf für vollständige Bereinigung
Wenn die Datei das Unternehmen verlässt und nichts aus der Metadaten‑Schicht überleben soll, verzichten Sie auf Prädikate.
# One call, every detected metadata package
with Metadata("board-report.docx") as metadata:
removed = metadata.sanitize()
metadata.save("board-report-final.docx")
print(f"sanitize() removed {removed} properties")
sanitize() löscht jedes von der Bibliothek erkannte Paket: Dokument‑Info‑Identitätsfelder, Kommentare, Revisionshistorie, Autoren von nachverfolgten Änderungen und benutzerdefinierte OOXML‑Teile. Das Verhalten ist auf der Seite Clean metadata dokumentiert. Seine Stärke ist zugleich sein Nachteil. Title und Subject verschwinden zusammen mit den PII, weshalb es am Export‑Tor und nicht mitten im Kollaborations‑Workflow eingesetzt werden sollte.
Brauche ich alle vier gezielten Durchläufe?
Nein. Jeder Durchlauf existiert, weil ein anderes Team das Risiko trägt. Identitätsfelder beunruhigen Datenschutzbeauftragte, Kommentarspuren das Rechts‑Team, Revisionszähler die Verhandler und Server‑Felder die Sicherheit. Führen Sie die Durchläufe aus, die zu Ihren Prüfern passen, in beliebiger Reihenfolge, da jeder seine eigene Ausgabekopie schreibt. Wenn niemand überlebende Felder benötigt, springen Sie direkt zu sanitize() und verifizieren.
Vergleich der drei Ansätze
| Methode | Am besten für | Wesentliche Vorteile | Einschränkungen |
|---|---|---|---|
| Tag‑gesteuerte Entfernung | Arbeitskopien, Multi‑Format‑Pipelines | Formatunabhängig, bewahrt beschreibende Felder | Deckt nur tag‑klassifizierte Konzepte ab |
| Namens‑Muster‑Entfernung | Kommentare, Revisionen, Server‑Felder | Erreicht benutzerdefinierte Eigenschaften, die Tags übersehen | Teilstrings müssen pro Umgebung abgestimmt werden |
| Vollständiges sanitize() | Endexport außerhalb des Unternehmens | Kann keine vergessene Eigenschaft übersehen | Löscht auch harmlose Felder |
Die Ansätze lassen sich natürlich kombinieren: gezielte Durchläufe, solange das Dokument aktiv ist, sanitize() beim Versand.
Verifizieren, bevor Sie vertrauen
Ein Entfernen‑Aufruf, der eine Anzahl zurückgibt, ist kein Beweis dafür, dass die Datei sauber ist. Das Repository beendet jeden Lauf, indem es die bereinigte Ausgabe erneut öffnet und mit find_properties scannt, wobei ein Prädikat verwendet wird, das die Tag‑Regeln und Namens‑Regeln aller oben genannten Durchläufe kombiniert.
def is_pii(p):
if p.name is None:
return False
return (
Tags.person.creator in list(p.tags)
or Tags.person.editor in list(p.tags)
or Tags.person.manager in list(p.tags)
or Tags.corporate.company in list(p.tags)
or any(n in p.name for n in (
"Comment", "Reviewer", "Revision", "TrackedChange",
"Classification", "Department", "Server", "Workflow")))
with Metadata("board-report-final.docx") as metadata:
for p in metadata.find_properties(is_pii):
value = (str(p.interpreted_value) if p.interpreted_value is not None
else (str(p.value) if p.value is not None else ""))
if value and value not in ("0", "0.0"):
print(f"LEAK {p.name}={value}")
Die vollständige Version im Repository sortiert Überlebende in zwei Buckets, und die Unterscheidung ist wichtig. Metadaten‑Lecks müssen null sein. Inhalte‑seitige Überbleibsel, Word‑Kommentar‑Ballons und nachverfolgte Änderungen in word/document.xml, sind Body‑Inhalte, die eine Metadaten‑API nicht erreichen kann; deren Entfernung erfordert eine Inhalts‑Bearbeitungs‑Bibliothek wie Aspose.Words. Ein ehrlicher Bericht nennt beide Buckets, anstatt den Sieg bereits beim ersten zu erklären. Beim ersten Durchlauf dieses Scans auf einer „sauberen“ Datei wurde ein Department‑Feld markiert, das eine Unternehmensvorlage stillschweigend seit Monaten wieder hinzufügte.
Best Practices und Tipps
- Kopien bereinigen, niemals Originale: Jedes Snippet hier schreibt in einen neuen Pfad und bewahrt das Original für Ihre Unterlagen und Aufbewahrungsregeln.
- Zählungen protokollieren: Die Rückgabewerte von
remove_propertiesundsanitize()bilden Ihr Audit‑Trail. Speichern Sie sie pro Datei, pro Durchlauf. - Verifizierung in CI einbinden: Ein Leak‑Check, der den Build fehlschlagen lässt, fängt Vorlagen‑Regressionen am Tag ihres Auftretens ab, nicht am Tag, an dem ein Kunde es bemerkt.
- Grenze zwischen Metadaten und Inhalt beachten: Meldet nie eine Datei als sauber, solange body‑level‑Kommentare verbleiben; stellen Sie sie als separaten Befund dar.
- Lizenzierung: Der Evaluierungsmodus reproduziert alles in diesem Artikel; verwenden Sie in der Produktion eine Lizenz, damit keine Evaluierungs‑Markierungen ausgehende Dateien berühren.
Fazit
Drei Ansätze, eine Entscheidungsregel. Nutzen Sie Tags, wenn das Konzept klassifiziert ist und die Datei weiterhin nutzbar bleiben muss. Nutzen Sie Namen, wenn die Familie in benutzerdefinierten Eigenschaften lebt. Rufen Sie sanitize() auf, wenn die Datei die Vertrauensgrenze überschreitet, und verifizieren Sie mit einem Rücklese‑Scan, welchen Weg Sie auch gewählt haben.
Bereit, tiefer einzusteigen? Hier sind einige nächste Schritte:
- Studieren Sie die Prädikat‑Oberfläche auf der Seite Remove metadata properties der Dokumentation
- Folgen Sie dem step-by-step use case guide basierend auf demselben Code
- Klonen Sie das sample repository und führen Sie die behauptete Pipeline gegen Ihre eigenen Dateien aus
Zusätzliche Ressourcen
- GroupDocs.Metadata Documentation
- API Reference
- Sample Projects on GitHub
- GroupDocs.Metadata Blog Category
Haben Sie Fragen oder möchten Ihre Implementierung teilen? Kontaktieren Sie uns im support forum.