วิธีทำงานกับหมายเหตุ PDF ใน Python

วิธีทำงานกับหมายเหตุ PDF ใน Python

Aspose.PDF FOSS for Python เปิดเผยทุกคำอธิบายบนหน้าเป็นวัตถุ Annotation ที่สดผ่าน AnnotationCollection ของหน้า, ดังนั้นคุณสามารถเพิ่มการทำเครื่องหมาย, ลิงก์, และคำอธิบาย 3D, ตรวจสอบคุณสมบัติเฉพาะประเภทของมัน, และสร้างสตรีมการแสดงผลที่โปรแกรมอ่าน PDF ต้องการเพื่อเรนเดอร์ — ทั้งหมดจาก Python แท้ๆ. คู่มือนี้แสดงวิธีการติดตั้งไลบรารี, เพิ่มคำอธิบาย, อ่านกลับ, และสร้างสตรีมการแสดงผลของมัน.

คู่มือแบบทีละขั้นตอน

ขั้นตอนที่ 1: ติดตั้งแพคเกจ

ติดตั้งแพคเกจ FOSS Aspose.PDF:

git clone https://github.com/aspose-pdf-foss/Aspose-PDF-FOSS-for-Python.git
cd Aspose-PDF-FOSS-for-Python
pip install -e .

ตรวจสอบการติดตั้งโดยการนำเข้าโมดูลระดับบนสุด aspose_pdf, ซึ่งเปิดเผยคลาส Document ที่ใช้ในขั้นตอนด้านล่าง. โค้ดส่วนนี้จะแสดงผล aspose_pdf OK เมื่อการนำเข้าประสบความสำเร็จ; ModuleNotFoundError ปกติหมายถึงแพคเกจถูกติดตั้งในสภาพแวดล้อม Python ที่แตกต่างจากที่สคริปต์ของคุณกำลังทำงานอยู่:

import aspose_pdf
print("aspose_pdf OK")

ขั้นตอนที่ 2: นำเข้าคลาสที่จำเป็น

นำเข้า Document เพื่อเก็บ PDF, รวมถึงคลาสคำอธิบายที่คุณจะใช้สร้างและตรวจสอบคำอธิบาย:

from aspose_pdf import Document
from aspose_pdf.annotations import (
    Annotation,
    AnnotationType,
    AnnotationFlags,
    MarkupAnnotation,
    LinkAnnotation,
)

ขั้นตอนที่ 3: เพิ่มคำอธิบายลงในหน้า

แต่ละ Page เปิดเผยคำอธิบายของมันผ่านคุณสมบัติ annotations, ซึ่งเป็น AnnotationCollection. เรียก add(subtype, rect, contents) พร้อมชื่อชนิดย่อย, สี่เหลี่ยม (left, bottom, right, top), และเนื้อหาข้อความของคำอธิบาย. ชนิดย่อยของการทำเครื่องหมายมาตรฐานเช่น "Highlight" จะถูกส่งคืนเป็นอินสแตนซ์ของ MarkupAnnotation:

from aspose_pdf import Document

document = Document()
document.pages.add()
page = document.pages[0]

annotation = page.annotations.add(
    "Highlight",
    (100, 700, 300, 720),
    "Key clause",
)
print(type(annotation).__name__)   # MarkupAnnotation
print(annotation.contents)         # Key clause

ขั้นตอนที่ 4: สร้างคำอธิบายจากชนิดย่อยแบบ Enum

AnnotationType แสดงรายการทุกชนิดย่อยของคำอธิบาย PDF มาตรฐาน (PDF 32000-1:2008, ตาราง 169), ดังนั้นคุณสามารถส่งสมาชิก enum แทนสตริงดิบได้. ข้อมูลที่เฉพาะประเภท — เช่น เวอร์เท็กซ์ของโพลิกอน — จะอยู่ในพจนานุกรม properties และจะถูกอ่านกลับด้วย get_property:

from aspose_pdf import Document
from aspose_pdf.annotations import AnnotationType

document = Document()
document.pages.add()
page = document.pages[0]

annotation = page.annotations.add(
    AnnotationType.POLYGON,
    (0, 0, 10, 10),
    "",
    properties={"Vertices": [0, 0, 10, 0, 5, 10]},
)
print(annotation.subtype)                    # Polygon
print(annotation.get_property("Vertices"))   # [0, 0, 10, 0, 5, 10]

ขั้นตอนที่ 5: อ่านและวนซ้ำคำอธิบายที่มีอยู่

AnnotationCollection สามารถวนซ้ำได้, ดังนั้นคุณสามารถเดินผ่านทุกคำอธิบายที่อยู่บนหน้าแล้ว — รวมถึงที่โหลดจาก PDF ที่มีอยู่แล้ว — และอ่านคุณสมบัติทั่วไปที่ทุก Annotation เปิดเผย (subtype, contents, rect, title, author, color):

from aspose_pdf import Document

document = Document()
document.pages.add()
page = document.pages[0]
page.annotations.add("Text", (50, 50, 70, 70), "First note")
page.annotations.add("Text", (80, 80, 100, 100), "Second note")

for annotation in page.annotations:
    print(annotation.subtype, "-", annotation.contents)

ขั้นตอน 6: สร้าง Annotation Appearance Streams

คำอธิบายที่สร้างโดยไม่มี appearance_normal อย่างชัดเจนจะไม่มีการแสดงผลที่มองเห็นได้ (/AP /N) จนกว่าจะมีการสร้างขึ้น เรียก generate_appearance(force) บน Annotation เดียว หรือ generate_appearances(force) บน AnnotationCollection ทั้งหมดเพื่อสังเคราะห์สตรีมลักษณะการแสดงผลที่ขาดหายทั้งหมดในหน้าเดียวกัน:

from aspose_pdf import Document
from aspose_pdf.engine.cos import AnnotationName

document = Document()
document.pages.add()
page = document.pages[0]

stamp = page.annotations.add(
    "Stamp",
    (100, 100, 260, 150),
    "",
    properties={"Name": AnnotationName("Approved")},
)
if stamp.generate_appearance():
    print(f"Appearance stream: {len(stamp.appearance_normal)} byte(s)")

# Regenerate every missing appearance stream on the page in one call:
count = page.annotations.generate_appearances(force=True)
print(f"Regenerated {count} appearance stream(s)")

ขั้นตอน 7: แยกแยะ Annotation Subclasses

AnnotationCollection.add() ส่งต่อไปยัง subclass เฉพาะตาม subtype: subtype แบบ markup (Highlight, Square, Stamp และอื่น ๆ) จะถูกส่งกลับเป็น MarkupAnnotation และ "Link" จะถูกส่งกลับเป็น LinkAnnotation. ทั้งสองสืบทอดเมธอดและพร็อพเพอร์ตี้ทั้งหมดจาก Annotation ดังนั้นการตรวจสอบ isinstance จะทำให้คุณแยกประเภท annotation ได้โดยไม่ต้องตรวจสอบสตริง subtype โดยตรง:

from aspose_pdf import Document
from aspose_pdf.annotations import LinkAnnotation, MarkupAnnotation

document = Document()
document.pages.add()
page = document.pages[0]

link = page.annotations.add("Link", (50, 750, 200, 770), "")
highlight = page.annotations.add("Highlight", (50, 700, 200, 720), "")

print(isinstance(link, LinkAnnotation))         # True
print(isinstance(highlight, MarkupAnnotation))  # True

ปัญหาที่พบบ่อยและวิธีแก้

get_property returns None สำหรับคุณสมบัติที่ฉันเพิ่งตั้งค่า

properties คีย์ต้องตรงกันและคำนึงถึงตัวพิมพ์ใหญ่/เล็กของชื่อฟิลด์ PDF ("Vertices", "Name" และอื่น ๆ) — การพิมพ์ผิดหรือกรณีตัวอักษรที่ไม่ถูกต้องจะถูกละเว้นอย่างเงียบโดยไม่แจ้งข้อผิดพลาด ส่งอาร์กิวเมนต์ default ไปยัง get_property(name, default) และตรวจสอบอย่างชัดเจนขณะดีบัก subtype ใหม่.

generate_appearance() returns False

ไม่ใช่ทุกการจับคู่ของประเภทย่อยและคุณสมบัติที่สามารถสังเคราะห์เป็นสตรีมลักษณะโดยตัวสร้างในตัวได้ ตรวจสอบ has_appearance ก่อนสมมติว่าการเรียกสำเร็จ และจัดหา appearance_normal ที่เรนเดอร์ล่วงหน้า (bytes) โดยตรงบน add() สำหรับประเภทย่อยที่ตัวสร้างไม่ครอบคลุม.

คลาสย่อยของ annotation ที่ไม่คาดคิดหลังจาก add()

สตริงประเภทย่อย (หรือสมาชิก AnnotationType) ที่คุณส่งจะกำหนดคลาสที่คืนค่า: ประเภทย่อยของ markup จะกลับมาเป็น MarkupAnnotation, "Link" จะกลับมาเป็น LinkAnnotation, และประเภทย่อยที่รู้จักอื่นใดจะกลับมาเป็น Annotation พื้นฐาน ใช้ isinstance() กับ MarkupAnnotation/LinkAnnotation แทนการสมมติสตริงประเภทย่อยเฉพาะ.

AnnotationFlags ค่าดูเหมือนไม่เปลี่ยนการเรนเดอร์

AnnotationFlags (PRINT, HIDDEN, NO_ZOOM, READ_ONLY และที่คล้ายกัน) เป็น enum มาตรฐานของ Python IntFlag สำหรับการประกอบและตีความบิตพฤติกรรมของคำอธิบายด้วยตัวดำเนินการ | — เป็นประเภทค่า ไม่ใช่คุณสมบัติที่ Annotation.add() เขียนอัตโนมัติ ผสานรวมธงที่คุณต้องการและส่งผ่านกลไก properties เฉพาะประเภทเดียวกันที่ใช้สำหรับข้อมูลเฉพาะประเภทย่อยอื่น ๆ.

ทำงานกับหน้า ที่ยังไม่มีคำอธิบายใด ๆ

page.annotations จะเป็น AnnotationCollection ที่ถูกต้องเสมอ (อาจว่างเปล่า) — คุณไม่จำเป็นต้องตรวจสอบ None ก่อนเรียก add(), ทำการวนลูป, หรือเรียก clear().

คำถามที่พบบ่อย

ประเภทย่อยของ annotation ใดที่ Aspose.PDF FOSS สำหรับ Python รองรับ?

AnnotationType แสดงรายการประเภทย่อยมาตรฐาน PDF 32000-1:2008 Table 169 ทั้งหมด 25 ประเภท รวมถึง TEXT, LINK, FREE_TEXT, LINE, SQUARE, CIRCLE, POLYGON, HIGHLIGHT, STAMP, INK, FILE_ATTACHMENT, REDACT และอื่น ๆ.

ไลบรารีนี้รองรับ annotation 3D หรือไม่?

ใช่. PDF3DAnnotation, พร้อมกับ PDF3DArtwork, PDF3DContent, PDF3DView, PDF3DLightingScheme, และ PDF3DRenderMode, สร้างโมเดลพื้นผิว annotation PDF 3D ขั้นพื้นฐาน (สี่เหลี่ยม, งานศิลปะฝังตัว, และมุมมองที่ตั้งชื่อ) สำหรับเวิร์กโฟลว์ PDF 3D ก่อนปล่อย. ดูที่ อ้างอิง PDF3DAnnotation สำหรับชุดคุณสมบัติทั้งหมดของมัน.

ฉันจะลบ annotation จากหน้าอย่างไร?

เรียก page.annotations.delete(index) เพื่อลบ annotation หนึ่งรายการตามตำแหน่ง หรือ page.annotations.clear() เพื่อลบ annotation ทั้งหมดบนหน้า.

ฉันสามารถแทรก annotation ในตำแหน่งเฉพาะแทนการต่อท้ายได้หรือไม่?

ใช่ — AnnotationCollection.insert(index, subtype, rect, contents, title, appearance_normal, properties) รับอาร์กิวเมนต์เดียวกันกับ add() พร้อมกับเป้าหมาย index.

สีของ annotation แสดงอย่างไร?

คุณสมบัติ color บน Annotation (และคลาสย่อยของมัน) เป็น tuple[float, ...] ที่ตรงกับจำนวนส่วนประกอบของรายการ PDF /C (ว่างเมื่อสีไม่ได้ตั้งค่า) — ไม่ใช่วัตถุสีเฉพาะ.

ดูเพิ่มเติม

 ภาษาไทย