💡 مثال کامل و قابل اجرا در GitHub موجود است:
sanitize-office-document-pii-python

داده‌ای که هیچ‌کس قبل از ارسال مرور نمی‌کند

یک گزارش فصلی هیئت مدیره برای حسابرس خارجی ارسال می‌شود. متن آن بی‌نقص است؛ سه دوره بازبینی این را تضمین کرده‌اند. اما خود فایل داستان دیگری دارد. ویژگی‌های آن هنوز نام تحلیل‌گری که آن را تهیه کرده، مدیرِی که بازنویسی کرده، زیرمجموعهٔ شرکتی که قالب را مالک است، زمان‌مهر LastPrinted از شب قبل از مهلت، و شناسهٔ تأییدکنندهٔ SharePoint از جریان کار داخلی را شامل می‌شود. هیچ‌یک از این‌ها در صفحه‌ای ظاهر نمی‌شود. همهٔ آن‌ها همراه فایل می‌روند.

حذف PII یک جریان کاری GroupDocs.Metadata برای Python از طریق .NET است که این ویژگی‌های حاوی هویت را به‌صورت برنامه‌نویسی از فایل‌های Word، Excel و PowerPoint حذف می‌کند. این مقاله سه رویکردی که API ارائه می‌دهد مقایسه می‌کند: حذف مبتنی بر برچسب برای فیلدهای هویتی، حذف مبتنی بر الگوی نام برای خانواده‌های ویژگی مانند نظرات و بازنگری‌ها، و فراخوانی تک‌مرحله‌ای sanitize() که همه چیز را پاک می‌کند. همچنین گامی را می‌بینید که اکثر اسکریپت‌های پاک‌سازی از آن عبور می‌کنند: اسکن تأییدی که ثابت می‌کند پاک‌سازی واقعاً انجام شده است.

چرا PII متادیتا شایستگی یک خط لولهٔ جداگانه را دارد

ابزارهای بررسی محتوا آنچه مردم می‌خوانند را بررسی می‌کنند. آنچه سیستم‌های فایل ذخیره می‌کنند را بررسی نمی‌کنند و همین شکاف منبع حوادث انطباق است. یک درخواست GDPR شامل داده‌های شخصی در فیلدهای Author و Manager به همان اندازه داده‌های متنی می‌شود. کشف قانونی شمارنده‌های بازنگری و مجموع زمان ویرایش را می‌خواند تا مدت زمان مذاکره یک مقالهٔ موقعیتی را بازسازی کند. بازبینان مناقصه می‌توانند ساختار سازمانی شما را از ویژگی‌های جریان کار SharePoint استخراج کنند و فیلدهای نظرات یک اطلاعیهٔ مطبوعاتی نام بازبین‌ها را همراه با نظرات مرحلهٔ پیش‌نویس حفظ می‌کند. هر یک از این‌ها یک یافته است. هیچ‌یک از آن‌ها در بدنهٔ سند قابل مشاهده نیست.

پیش‌نیازها

قبل از شروع، اطمینان حاصل کنید که:

  • Python 3 به همراه pip
  • GroupDocs.Metadata برای Python از طریق .NET، در مخزن نمونه به نسخهٔ ۲۶.۵ ثابت شده است
  • یک فایل Office با ویژگی‌های واقعی برای تمرین

نصب

pip install groupdocs-metadata-net==26.5

مخزن همراه یک فایل DOCX نمونه می‌کارد و هر قطعه کد زیر را به‌عنوان یک خط لولهٔ تأیید شده اجرا می‌کند.

روش ۱: حذف هویت مبتنی بر برچسب

چهار فیلد حساس‌ترین، Author, LastSavedBy, Manager و Company، نام‌های داخلی متفاوتی در قالب‌های Office دارند. سیستم برچسب این مشکل را حل می‌کند: به‌جای نام‌گذاری ویژگی‌ها، پیش‌شرط همهٔ مواردی را که به‌عنوان شخص یا شرکت برچسب‌گذاری شده‌اند، می‌گیرد.

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

نکات کلیدی:

  • استقلال قالب: همان لامبدا برای DOCX، XLSX و PPTX کار می‌کند زیرا برچسب‌ها بر اساس نقش طبقه‌بندی می‌شوند.
  • نتیجه‌گیری قابل شمارش: remove_properties تعداد ویژگی‌های منطبق را برمی‌گرداند که باید در لاگ حسابرسی شما ثبت شود.
  • معنای کپی: ذخیره در مسیر جدید، اصل را برای سوابق شما حفظ می‌کند.

💡 نکته: این عبور، فیلدهای Title, Subject و سایر فیلدهای توصیفی را حفظ می‌کند، بنابراین فایل برای جستجو و ایندکس‌گذاری DMS دوستانه می‌ماند.

روش ۲: حذف مبتنی بر الگوی نام برای خانواده‌های ویژگی

برچسب‌ها مفاهیم طبقه‌بندی‌شده را پوشش می‌دهند. خانواده‌های کامل فیلدهای نشت‌کننده خارج از این طبقه‌بندی قرار دارند: ویژگی‌های نظرات، شمارنده‌های بازنگری، مهرهای کاری جریان SharePoint. برای این‌ها، بر روی نام ویژگی خود مطابقت می‌دهیم.

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

همین شکل برای دو خانوادهٔ دیگر نیز کار می‌کند؛ فقط لیست زیررشته‌ها تغییر می‌کند:

خانواده زیررشته‌های مورد مطابقت
ردپای بازنگری Revision, TrackedChange, LastPrinted, TotalEditingTime, EditTime
سرور / جریان کار Server, Workflow, Approver, ContentType, Template

این روش دقت را برای پوشش بیشتر فدا می‌کند: "Comment" همچنین Comments و CommentCount را می‌گیرد که معمولاً همان چیزی است که یک عبور پاک‌سازی می‌خواهد. زیررشته‌های گسترده می‌توانند فیلدهای بی‌ضرر قالب را نیز بگیرند، بنابراین تعداد بازگشتی را نسبت به انتظارات بررسی کنید.

💡 نکته: هر خانواده را به‌عنوان عبور جداگانه اجرا کنید وقتی لاگ حسابرسی شما به شمارش‌های دسته‌ای نیاز دارد؛ وقتی این‌طور نیست زیررشته‌ها را در یک پیش‌شرط ترکیب کنید.

روش ۳: فراخوانی تک‌مرحله‌ای sanitize()

وقتی فایل در حال خروج از سازمان است و هیچ‌یک از لایهٔ متادیتا باید باقی بماند، نوشتن پیش‌شرط‌ها را متوقف کنید.

# 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() تمام بسته‌های متادیتایی که کتابخانه شناسایی می‌کند را پاک می‌کند: فیلدهای هویتی اطلاعات سند، نظرات، تاریخچه بازنگری، نویسندگان تغییرات ردیابی‌شده و بخش‌های سفارشی OOXML. رفتار آن در صفحهٔ Clean metadata مستند شده است. قوت آن همان هزینه‌اش است. Title و Subject همراه با PII ناپدید می‌شوند، به همین دلیل این متد بهتر است در نقطهٔ خروجی نهایی به‌کار رود نه در میانهٔ یک جریان کاری همکاری.

آیا به همهٔ چهار عبور هدفمند نیاز دارم؟

خیر. هر عبور به این دلیل وجود دارد که تیم متفاوتی ریسک مربوطه را در اختیار دارد. فیلدهای هویتی حریم خصوصی را به‌هم می‌زنند، ردپای نظرات مسائل قانونی، شمارنده‌های بازنگری مذاکرات‌کنندگان و فیلدهای سرور امنیت را به‌هم می‌ریزند. عبورهایی را اجرا کنید که با بازبینان شما مطابقت دارند، به هر ترتیبی، چون هر کدام نسخهٔ خروجی خود را می‌نویسند. وقتی هیچ‌فیلدی برای بقا لازم نیست، مستقیماً به sanitize() بروید و تأیید کنید.

مقایسهٔ سه رویکرد

روش مناسب برای مزایای کلیدی محدودیت‌ها
حذف مبتنی بر برچسب نسخه‌های کاری، خطوط لولهٔ چندقالبی مستقل از قالب، فیلدهای توصیفی را حفظ می‌کند فقط مفاهیم طبقه‌بندی‌شده توسط برچسب را پوشش می‌دهد
حذف مبتنی بر الگوی نام نظرات، بازنگری‌ها، فیلدهای سرور به ویژگی‌های سفارشی که برچسب نمی‌خورند می‌رسد زیررشته‌ها باید برای هر محیط تنظیم شوند
sanitize() کامل خروج نهایی خارج از سازمان نمی‌تواند ویژگی فراموش‌شده‌ای بماند فیلدهای بی‌ضرر را نیز پاک می‌کند

این رویکردها به‌صورت طبیعی ترکیب می‌شوند: عبورهای هدفمند در حالی که سند زنده است، و sanitize() هنگام ارسال.

پیش از اعتماد به نتایج، تأیید کنید

یک فراخوانی حذف که عددی برمی‌گرداند، شواهدی نیست که فایل پاک باشد. مخزن هر اجرا را با باز کردن خروجی پاک‌شده و اسکن آن با find_properties که پیش‌شرطی ترکیبی از قوانین برچسب و نام تمام عبورهای بالا است، پایان می‌دهد.

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

نسخهٔ کامل در مخزن بقاهای پیدا شده را به دو سطل تقسیم می‌کند و این تمایز مهم است. نشت‌های متادیتا باید صفر باشد. باقی‌مانده‌های سطح محتوا، حباب‌های نظرات Word و تغییرات ردیابی‌شده که داخل word/document.xml زندگی می‌کنند، محتوای بدنه هستند که API متادیتا نمی‌تواند به آن‌ها دسترسی پیدا کند؛ حذف آن‌ها نیاز به کتابخانهٔ ویرایش محتوا مانند Aspose.Words دارد. یک گزارش صادقانه هر دو سطل را نام می‌برد به‌جای اینکه پیروزی را فقط در اولین سطل اعلام کند. اولین باری که این اسکن را روی یک فایل «تمیز» اجرا کردم، فیلد Department را که یک قالب شرکتی به‌صورت ساکن برای ماه‌ها اضافه می‌کرد، شناسایی کرد.

بهترین روش‌ها و نکات

  • کپی‌های پاک‌شده، نه اصل‌ها: هر قطعه کد اینجا به مسیر جدید می‌نویسد و منبع را برای سوابق و قوانین نگهداری شما حفظ می‌کند.
  • ثبت شمارش‌ها: مقادیر بازگشتی remove_properties و sanitize() ردپای حسابرسی شما هستند. آن‌ها را برای هر فایل و هر عبور ذخیره کنید.
  • ادغام تأیید در CI: یک بررسی نشت که ساخت را متوقف می‌کند، رگرسیون‌های قالب را همان روزی که رخ می‌دهند می‌گیرد، نه روزی که مشتری متوجه می‌شود.
  • مرز متادیتا/محتوا را در نظر بگیرید: هرگز فایلی را «تمیز» گزارش ندهید در حالی که نظرات سطح بدنه باقی مانده‌اند؛ آن‌ها را به‌عنوان یافتهٔ جداگانه نشان دهید.
  • مجوز: حالت ارزیابی همه چیز را در این مقاله بازتولید می‌کند؛ در تولید از یک لایسنس استفاده کنید تا هیچ علامت ارزیابی‌ای به فایل‌های خروجی نچسبد.

نتیجه‌گیری

سه رویکرد، یک قاعده تصمیم‌گیری. وقتی مفهوم طبقه‌بندی‌شده است و فایل باید مفید بماند، با برچسب مطابقت دهید. وقتی خانواده در ویژگی‌های سفارشی زندگی می‌کند، با نام مطابقت دهید. وقتی فایل از مرز اعتماد عبور می‌کند، sanitize() را فراخوانی کنید و با اسکن بازخوانی مسیر انتخابی خود را تأیید کنید.

آمادهٔ عمیق‌تر شدن هستید؟ گام‌های بعدی عبارتند از:

منابع تکمیلی

سؤال دارید یا می‌خواهید پیاده‌سازی خود را به اشتراک بگذارید؟ در support forum با ما در ارتباط باشید.