💡 ตัวอย่างการทำงานเต็มที่มีบน GitHub:
sanitize-office-document-pii-python

The Data Nobody Reviews Before Hitting Send

รายงานคณะกรรมการรายไตรมาสถูกส่งให้ผู้ตรวจสอบภายนอก ข้อความในเอกสารปราศจากข้อผิดพลาด; มีการตรวจสอบสามรอบเพื่อให้แน่ใจเช่นนั้น แต่ไฟล์เองเป็นเรื่องอื่น คุณสมบัติของไฟล์ยังคงบ่งบอกชื่อของนักวิเคราะห์ที่ร่างเอกสาร, ผู้จัดการที่ทำการแก้ไข, บริษัทในเครือที่เป็นเจ้าของแม่แบบ, เวลาที่พิมพ์ครั้งสุดท้าย (LastPrinted) จากคืนก่อนกำหนด, และรหัสผู้อนุมัติใน SharePoint จากกระบวนการลงนามภายใน สิ่งเหล่านี้ไม่ได้ปรากฏบนหน้าใด ๆ ของเอกสาร แต่ทั้งหมดเดินทางพร้อมไฟล์ไปด้วย

การลบ PII เป็น workflow ของ 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 ในตัวอย่าง repository
  • ไฟล์ Office ที่มีคุณสมบัติจริงเพื่อฝึกฝน

Installation

pip install groupdocs-metadata-net==26.5

companion repository จะสร้างไฟล์ DOCX ตัวอย่างและรันโค้ดสคริปต์ทั้งหมดด้านล่างเป็น pipeline ที่ตรวจสอบแล้ว

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

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

แท็กครอบคลุมแนวคิดที่จัดประเภทไว้แล้ว แต่กลุ่มคุณสมบัติที่รั่วไหลหลาย ๆ อย่างอยู่นอกการจัดประเภทนั้น: คุณสมบัติคอมเมนต์, ตัวนับการแก้ไข, รหัสประจำกระบวนการทำงานของ 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")

รูปแบบเดียวกันนี้ใช้กับสองกลุ่มอื่น ๆ; เพียงรายการสับสตริงที่เปลี่ยนไป:

Family Substrings to match
Revision trail Revision, TrackedChange, LastPrinted, TotalEditingTime, EditTime
Server / workflow Server, Workflow, Approver, ContentType, Template

วิธีนี้แลกความแม่นยำเพื่อความครอบคลุม: "Comment" จะจับ Comments และ CommentCount ด้วย ซึ่งมักเป็นสิ่งที่ต้องการในการทำความสะอาด สับสตริงกว้างอาจจับฟิลด์แม่แบบที่ไม่มีอันตรายได้เช่นกัน ดังนั้นควรตรวจสอบจำนวนที่คืนค่าตรงกับความคาดหวัง

💡 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

เมื่อไฟล์กำลังออกจากองค์กรและไม่ต้องการให้ข้อมูลเมตาดาต้าใด ๆ คงอยู่ ให้หยุดเขียนตัวกำหนดเงื่อนไข

# 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

Method Best For Key Advantages Limitations
Tag-driven removal Working copies, multi-format pipelines Format-independent, preserves descriptive fields Only covers tag-classified concepts
Name-pattern removal Comments, revisions, server fields Reaches custom properties tags miss Substrings need tuning per environment
Full sanitize() Final export outside the organization Cannot miss a forgotten property Wipes harmless fields too

วิธีการเหล่านี้สามารถผสานกันได้อย่างเป็นธรรมชาติ: ใช้ขั้นตอนที่เจาะจงขณะเอกสารยังอยู่, แล้วใช้ sanitize() เมื่อส่งออก

Verify Before You Trust It

การเรียกลบที่คืนค่าจำนวนไม่ใช่หลักฐานว่าไฟล์สะอาด repository จะปิดทุกการรันด้วยการเปิดไฟล์ที่ทำความสะอาดแล้วใหม่และสแกนด้วย 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}")

เวอร์ชันเต็มใน repository จัดรายการที่เหลืออยู่เป็นสองกลุ่ม และความแตกต่างนี้สำคัญ การรั่วของเมตาดาต้าต้องเป็นศูนย์ ส่วนของเนื้อหาที่เหลืออยู่ เช่น ลูกศรคอมเมนต์ของ Word และการเปลี่ยนแปลงที่ติดตามใน word/document.xml เป็นเนื้อหาในส่วน body ที่ API เมตาดาต้าไม่สามารถเข้าถึงได้; การลบสิ่งเหล่านี้ต้องใช้ไลบรารีแก้ไขเนื้อหาเช่น Aspose.Words รายงานที่ซื่อสัตย์จะแสดงทั้งสองกลุ่มแทนการประกาศชนะในขั้นตอนแรก ครั้งแรกที่ฉันรันสแกนนี้บนไฟล์ “สะอาด” มันเจอฟิลด์ Department ที่เทมเพลตของบริษัทได้เพิ่มโดยเงียบ ๆ มาหลายเดือน

Best Practices and Tips

  • Sanitize copies, never originals: ทุกสคริปต์ที่นี่เขียนไปยังเส้นทางใหม่, ทำให้ต้นฉบับยังคงอยู่สำหรับบันทึกและกฎการเก็บรักษา
  • Log the counts: ค่าที่คืนจาก remove_properties และ sanitize() คือร่องรอยการตรวจสอบของคุณ เก็บไว้ต่อไฟล์ต่อการรันแต่ละครั้ง
  • Wire verification into CI: การตรวจสอบการรั่วที่ทำให้การ build ล้มเหลวจะจับการเปลี่ยนแปลงของเทมเพลตในวันเดียวที่เกิด, ไม่ใช่วันที่ลูกค้าตรวจพบ
  • Mind the metadata/content boundary: อย่าแจ้งว่าไฟล์สะอาดขณะที่คอมเมนต์ในระดับ body ยังคงอยู่; ให้แสดงเป็นการค้นพบแยกต่างหาก
  • Licensing: โหมดประเมินผลจะทำซ้ำทุกอย่างในบทความนี้; ใช้ไลเซนส์ในสภาพการผลิตเพื่อให้ไม่มีเครื่องหมายประเมินผลปรากฏบนไฟล์ที่ส่งออก

Conclusion

สามวิธี, กฎการตัดสินใจหนึ่งข้อ ใช้แท็กเมื่อแนวคิดถูกจัดประเภทและไฟล์ต้องยังคงใช้งานได้ ใช้ชื่อเมื่อกลุ่มอยู่ในคุณสมบัติที่กำหนดเอง เรียก sanitize() เมื่อไฟล์ข้ามขอบเขตความเชื่อถือ, และตรวจสอบด้วยการสแกนอ่านกลับไม่ว่าคุณจะเลือกวิธีใด

พร้อมจะลึกลงไปอีก? นี่คือขั้นตอนต่อไป:

  • ศึกษาพื้นผิวของตัวกำหนดเงื่อนไขในหน้าเอกสาร Remove metadata properties
  • ทำตาม step-by-step use case guide ที่สร้างจากโค้ดเดียวกัน
  • คัดลอก sample repository และรัน pipeline ที่ตรวจสอบแล้วกับไฟล์ของคุณเอง

Additional Resources

มีคำถามหรืออยากแชร์การนำไปใช้ของคุณ? ติดต่อได้ที่ support forum.