💡 مثال كامل يعمل متاح على GitHub:
sanitize-office-document-pii-python
The Data Nobody Reviews Before Hitting Send
تُرسل تقرير مجلس الإدارة ربع السنوي إلى مدقق خارجي. النص خالٍ من الأخطاء؛ ثلاث دورات مراجعة ضمنت ذلك. الملف نفسه قصة أخرى. لا تزال خصائصه تُظهر اسم المحلل الذي صاغه، والمدير الذي أعاد صياغته، والشركة الفرعية التي تملك القالب، وطابع زمن LastPrinted من الليلة التي سبقت الموعد النهائي، ومعرّف موافق SharePoint من سير عمل الاعتماد الداخلي. لا يظهر أي من هذا على أي صفحة. كل ذلك يسافر مع الملف.
إزالة المعلومات الشخصية (PII) هي سير عمل GroupDocs.Metadata للغة Python عبر .NET يزيل هذه الخصائص التي تحمل هوية من ملفات Word وExcel وPowerPoint برمجيًا. تُقارن هذه المقالة بين الثلاث طرق التي يقدمها API: الإزالة المدفوعة بالوسوم للحقول الهوية، الإزالة المدفوعة بنمط الاسم لعائلات الخصائص مثل التعليقات والمراجعات، والدالة الوحيدة sanitize() التي تمسح كل شيء. ستشاهد أيضًا الخطوة التي تتخطاها معظم سكريبتات التنظيف، وهي فحص التحقق الذي يثبت أن التنظيف تم فعلاً.
Why Metadata PII Deserves Its Own Pipeline
أدوات مراجعة المحتوى تتحقق مما يقرأه الأشخاص. لا تتحقق مما تخزّنه أنظمة الملفات، وهذه الفجوة هي مصدر حوادث الامتثال. طلب GDPR يغطي البيانات الشخصية في حقول Author وManager بقدر ما يغطي البيانات في النص. الاكتشاف القانوني يقرأ عدّادات المراجعات وإجماليات وقت التحرير لإعادة بناء مدة التفاوض على ورقة موقف. يمكن لمراجعي العطاءات رسم هيكل منظمتك من خصائص سير عمل SharePoint، وتحتفظ حقول التعليقات في بيان صحفي بأسماء المراجعين إلى جانب ملاحظات مرحلة المسودة. كل ذلك يُعدّ اكتشافًا. ولا أحد يرى أيًا منها في نص الوثيقة.
Prerequisites
قبل البدء، تأكد من وجود ما يلي:
- Python 3 مع pip
- GroupDocs.Metadata للغة Python عبر .NET، مثبت في مستودع العينة على الإصدار 26.5
- ملف Office يحتوي على خصائص حقيقية للتدرب عليها
Installation
pip install groupdocs-metadata-net==26.5
المستودع المرافق يزرع ملف DOCX نموذجي ويُنفّذ كل مقتطف أدناه كخط أنابيب مُؤكد.
Method 1: Tag-Driven Identity Removal
أكثر الحقول حساسيةً، وهي 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")
نقاط رئيسية:
- استقلالية الصيغة: نفس الدالة lambda تنظف DOCX وXLSX وPPTX لأن الوسوم تصنّف حسب الدور.
- نتيجة قابلة للعد:
remove_propertiesتُعيد عدد الخصائص التي طابقت، وهذا ما يُسجَّل في سجل التدقيق. - نسخ semantically: الحفظ إلى مسار جديد يبقي الأصل لسجلاتك.
💡 نصيحة: هذه العملية تحافظ على الحقول Title وSubject وغيرها من الحقول الوصفية، لذا يبقى الملف صديقًا للبحث وفهرسة أنظمة إدارة المستندات (DMS).
Method 2: Name-Pattern Removal for Property Families
الوسوم تغطي المفاهيم المصنّفة. عائلات كاملة من الحقول المتسربة تقع خارج هذا التصنيف: خصائص التعليقات، عدّادات المراجعات، طوابع سير عمل 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، وهو ما يرغبه عادةً تمرير التنظيف. السلاسل العامة قد تطابق حقول القالب غير الضارة أيضًا، لذا راقب العدد المرجع مقابل توقعاتك.
💡 نصيحة: شغّل كل عائلة كتمرير منفصل عندما يحتاج سجل التدقيق إلى عدّات لكل فئة؛ دمج السلاسل في مُعطى واحد عندما لا يكون ذلك ضروريًا.
Method 3: The One-Call Full 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، لذا يُفضَّل استخدامها عند بوابة التصدير وليس في وسط سير عمل التعاون.
Do I need all four targeted passes?
لا. كل تمرير موجود لأن فريقًا مختلفًا يتحمل المخاطر. حقول الهوية تُزعج مسؤولي الخصوصية، سلاسل التعليقات تُزعج القانونية، عدّادات المراجعات تُزعج المفاوضين، وحقول الخادم تُزعج الأمن. شغّل التمريرات التي تتطابق مع مراجعيك، بأي ترتيب، لأن كل واحدة تكتب نسختها الخاصة. عندما لا يحتاج أحد إلى حقول باقية، انتقل مباشرة إلى sanitize() وتحقق.
Comparing the Three Approaches
| الطريقة | الأنسب لـ | المزايا الرئيسية | القيود |
|---|---|---|---|
| Tag-driven removal | النسخ العاملة، خطوط أنابيب متعددة الصيغ | مستقل عن الصيغة، يحافظ على الحقول الوصفية | يغطي فقط المفاهيم المصنّفة بالوسوم |
| Name-pattern removal | التعليقات، المراجعات، حقول الخادم | يصل إلى الخصائص المخصّصة التي لا تغطيها الوسوم | تحتاج السلاسل النصية إلى ضبط حسب البيئة |
| Full sanitize() | التصدير النهائي خارج المؤسسة | لا يمكن أن يفوّت خاصية منسية | يمحو الحقول غير الضارة أيضًا |
تُركّب الأساليب بطبيعتها: تمريرات مستهدفة أثناء بقاء الوثيقة، sanitize() عند شحنها.
Verify Before You Trust It
إرجاع عدد من عملية الإزالة ليس دليلًا على أن الملف نظيف. ينهي المستودع كل تشغيل بإعادة فتح المخرجات المنقاة ومسحها باستخدام 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—هي محتوى نصي لا يمكن لواجهة برمجة بيانات وصفية الوصول إليه؛ إزالتها تتطلب مكتبة تحرير محتوى مثل Aspose.Words. تقرير صادق يذكر كلا الدلوين بدلاً من إعلان النصر بعد الفحص الأول. في المرة الأولى التي شغلت فيها هذا الفحص على ملف “نظيف”، أشار إلى حقل Department كان قالب الشركة يضيفه بهدوء لعدة أشهر.
Best Practices and Tips
- نظّف النسخ، لا الأصلي: كل مقتطف هنا يكتب إلى مسار جديد، محافظًا على المصدر لسجلاتك وقواعد الاحتفاظ.
- سجّل الأعداد: القيم المرجعية لـ
remove_propertiesوsanitize()هي سجل التدقيق الخاص بك. احفظها لكل ملف، لكل تمرير. - دمج التحقق في CI: فحص التسرب الذي يفشل البناء يلتقط تراجع القوالب في اليوم الذي يحدث فيه، لا في اليوم الذي يلاحظه العميل.
- احذر حد الفاصل بين البيانات الوصفية والمحتوى: لا تُعلن أن الملف نظيف بينما تبقى تعليقات على مستوى النص؛ اعرضها كاكتشاف منفصل.
- الترخيص: وضع التقييم يُعيد كل شيء في هذه المقالة؛ استخدم ترخيصًا في الإنتاج حتى لا تلمس علامات التقييم الملفات الصادرة.
Conclusion
ثلاث طرق، قاعدة قرار واحدة. طابق بالوسم عندما يكون المفهوم مُصنّفًا ويجب أن يبقى الملف مفيدًا. طابق بالاسم عندما تعيش العائلة في خصائص مخصّصة. استدعِ sanitize() عندما يعبر الملف حدود الثقة، وتحقق بمسح قراءة عكسي مهما كان المسار الذي اخترته.
هل تريد الغوص أعمق؟ إليك بعض الخطوات التالية:
- ادرس سطح المُعطى في صفحة وثائق Remove metadata properties
- اتبع دليل الحالة الاستخدامية step-by-step use case guide المبني على نفس الكود
- استنسخ المستودع العيني وشغّل خط الأنابيب المؤكد ضد ملفاتك الخاصة
Additional Resources
هل لديك أسئلة أو تريد مشاركة تنفيذك؟ تواصل عبر support forum.