💡 Full working example available on GitHub:
sanitize-office-document-pii-python

The Data Nobody Reviews Before Hitting Send

Kwartalny raport zarządu jest wysyłany do zewnętrznego audytora. Tekst jest nieskazitelny; trzy cykle recenzji to potwierdziły. Sam plik to inna historia. Jego właściwości wciąż zawierają imię i nazwisko analityka, który go opracował, menedżera, który go przerobił, spółkę zależną, której należy szablon, znacznik czasu LastPrinted z nocy przed terminem oraz identyfikator zatwierdzającego w SharePoint z wewnętrznego procesu akceptacji. Nic z tego nie pojawia się na żadnej stronie. Wszystko to podróżuje razem z plikiem.

Usuwanie PII to przepływ pracy GroupDocs.Metadata dla Pythona poprzez .NET, który programowo usuwa te właściwości niosące tożsamość z plików Word, Excel i PowerPoint. Ten artykuł porównuje trzy podejścia oferowane przez API: usuwanie oparte na tagach dla pól tożsamości, usuwanie oparte na wzorcach nazw dla rodzin właściwości takich jak komentarze i wersje, oraz jednorazowe wywołanie sanitize(), które czyści wszystko. Zobaczysz także krok, który pomijają większość skryptów sanitizujących – skan weryfikacyjny, który dowodzi, że czyszczenie rzeczywiście się powiodło.

Why Metadata PII Deserves Its Own Pipeline

Narzędzia do przeglądu treści sprawdzają, co ludzie czytają. Nie sprawdzają, co systemy plików przechowują, a właśnie w tej luce powstają incydenty zgodności. Żądanie GDPR obejmuje dane osobowe w polach Author i Manager tak samo, jak dane w treści. Odkrycie prawne odczytuje liczniki wersji i sumy czasu edycji, aby odtworzyć, jak długo negocjowano dokument. Recenzenci przetargów mogą odtworzyć strukturę organizacyjną z właściwości przepływu pracy SharePoint, a pola komentarzy w komunikacie prasowym zachowują nazwiska recenzentów obok uwag w fazie szkicu. Każde z nich to znalezisko. Żadne nie jest widoczne w treści dokumentu.

Prerequisites

Przed rozpoczęciem upewnij się, że masz:

  • Python 3 z pip
  • GroupDocs.Metadata dla Pythona poprzez .NET, zablokowaną w repozytorium przykładowym do wersji 26.5
  • Plik Office z rzeczywistymi właściwościami do ćwiczeń

Installation

pip install groupdocs-metadata-net==26.5

companion repository dostarcza przykładowy DOCX i uruchamia każdy fragment kodu jako zweryfikowany potok.

Method 1: Tag-Driven Identity Removal

Cztery najczułe pola – Author, LastSavedBy, Manager i Company – mają różne wewnętrzne nazwy w formatach Office. System tagów rozwiązuje ten problem: zamiast nazywać właściwości, predykat pyta o wszystko oznaczone jako osoba lub firma.

# 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")

Key points:

  • Format independence: the same lambda cleans DOCX, XLSX, and PPTX because tags classify by role.
  • Countable outcome: remove_properties returns how many properties matched, which belongs in your audit log.
  • Copy semantics: saving to a new path keeps the original for your records.

💡 Tip: this pass preserves Title, Subject, and other descriptive fields, so the file stays friendly to search and DMS indexing.

Method 2: Name-Pattern Removal for Property Families

Tagi obejmują sklasyfikowane pojęcia. Całe rodziny wyciekających pól znajdują się poza tą klasyfikacją: właściwości komentarzy, liczniki wersji, znaczniki przepływu pracy SharePoint. Dla nich dopasowujemy się do samej nazwy właściwości.

# 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")

Ten sam schemat obsługuje pozostałe dwie rodziny; zmienia się jedynie lista podciągów:

Rodzina Podciągi do dopasowania
Ścieżka wersji Revision, TrackedChange, LastPrinted, TotalEditingTime, EditTime
Serwer / przepływ pracy Server, Workflow, Approver, ContentType, Template

To wymiana precyzji na zasięg: "Comment" łapie także Comments i CommentCount, co zazwyczaj jest pożądane w procesie sanitizacji. Szerokie podciągi mogą również dopasować nieszkodliwe pola szablonu, więc porównaj zwróconą liczbę z oczekiwaniami.

💡 Tip: run each family as its own pass when your audit log needs per‑category counts; merge the substrings into one predicate when it does not.

Method 3: The One-Call Full Sanitize

Gdy plik opuszcza organizację i nic w warstwie metadanych nie powinno przetrwać, przestań pisać predykaty.

# 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() usuwa każdy pakiet metadanych wykryty przez bibliotekę: pola tożsamości w informacji o dokumencie, komentarze, historię wersji, autorów zmian śledzonych oraz niestandardowe części OOXML. Zachowanie jest opisane na stronie Clean metadata. Jego siła jest jednocześnie kosztem. Title i Subject znikają razem z PII, dlatego wywołanie to powinno znajdować się na bramce eksportu, a nie w środku współpracy.

Do I need all four targeted passes?

Nie. Każde z nich istnieje, ponieważ inny zespół odpowiada za ryzyko. Pola tożsamości niepokoją oficerów prywatności, ścieżki komentarzy niepokoją prawników, liczniki wersji niepokoją negocjatorów, a pola serwerowe niepokoją bezpieczeństwo. Uruchamiaj te, które odpowiadają Twoim recenzentom, w dowolnej kolejności, ponieważ każdy zapisuje własną kopię wyjściową. Gdy nikt nie potrzebuje zachowanych pól, przejdź od razu do sanitize() i zweryfikuj.

Comparing the Three Approaches

Metoda Najlepsze zastosowanie Kluczowe zalety Ograniczenia
Tag-driven removal Kopie robocze, wieloformatowe potoki Niezależność od formatu, zachowuje pola opisowe Obejmuje tylko pojęcia sklasyfikowane tagami
Name-pattern removal Komentarze, wersje, pola serwerowe Sięga do własności niestandardowych, które tagi pomijają Podciągi wymagają dostrojenia do środowiska
Full sanitize() Końcowy eksport poza organizację Nie może pominąć żadnej zapomnianej właściwości Usuwa także nieszkodliwe pola

Podejścia komponują się naturalnie: ukierunkowane przebiegi, gdy dokument jest aktywny, oraz sanitize() przy wysyłce.

Verify Before You Trust It

Zwrócona liczba usuniętych właściwości nie jest dowodem, że plik jest czysty. Repozytorium kończy każdy przebieg ponownym otwarciem wyczyszczonego wyjścia i skanowaniem go metodą find_properties, używając predykatu łączącego reguły tagów i nazwy ze wszystkich powyższych przebiegów.

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}")

Pełna wersja w repozytorium sortuje pozostałości do dwóch koszyków, a rozróżnienie ma znaczenie. Wycieki metadanych muszą wynosić zero. Resztki na poziomie treści – balony komentarzy Worda i zmiany śledzone wewnątrz word/document.xml – to zawartość, której API metadanych nie może dotrzeć; ich usunięcie wymaga biblioteki edytującej treść, takiej jak Aspose.Words. Rzetelny raport wymienia oba koszyki zamiast ogłaszać zwycięstwo po pierwszym. Przy pierwszym uruchomieniu tego skanu na „czystym” pliku wykryto pole Department, które szablon korporacyjny cicho dodawał od miesięcy.

Best Practices and Tips

  • Sanitize copies, never originals: każdy fragment kodu zapisuje do nowej ścieżki, zachowując źródło dla Twoich zapisów i reguł retencji.
  • Log the counts: zwracane wartości remove_properties i sanitize() są Twoim śladem audytu. Przechowuj je per plik, per przebieg.
  • Wire verification into CI: kontrola wycieków, która przerywa build, łapie regresje szablonów w dniu ich wystąpienia, a nie w dniu, w którym klient to zauważy.
  • Mind the metadata/content boundary: nigdy nie deklaruj pliku jako czystego, gdy w treści pozostają komentarze; zgłoś je jako odrębne znalezisko.
  • Licensing: tryb ewaluacji odtwarza wszystko w tym artykule; użyj licencji w produkcji, aby żadne oznaczenia ewaluacji nie trafiły do wychodzących plików.

Conclusion

Trzy podejścia, jedna reguła decyzyjna. Dopasuj tag, gdy pojęcie jest sklasyfikowane i plik musi pozostać użyteczny. Dopasuj nazwę, gdy rodzina mieszka w własnościach niestandardowych. Wywołaj sanitize(), gdy plik przekracza granicę zaufania, i zweryfikuj go skanem odczytu, niezależnie od wybranej ścieżki.

Gotowy na głębsze zanurzenie? Oto kolejne kroki:

Additional Resources

Have questions or want to share your implementation? Reach out on the support forum.