Hur man arbetar med PDF-anteckningar i Python

Hur man arbetar med PDF-anteckningar i Python

Aspose.PDF FOSS för Python exponerar varje annotation på en sida som ett levande Annotation-objekt via sidans AnnotationCollection, så att du kan lägga till markup-, länk- och 3D-annotationer, inspektera deras typ-specifika egenskaper och generera de appearance streams som PDF-visare behöver för att rendera dem — allt från ren Python. Den här guiden visar hur du installerar biblioteket, lägger till annotationer, läser tillbaka dem och genererar deras appearance streams.

Steg-för-steg-guide

Steg 1: Installera paketet

Installera Aspose.PDF FOSS-paketet:

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

Verifiera installationen genom att importera top-level aspose_pdf-modulen, som exponerar Document-klassen som används i stegen nedan. Kodsnutten skriver ut aspose_pdf OK när importen lyckas; en ModuleNotFoundError betyder vanligtvis att paketet installerades i en annan Python-miljö än den som kör ditt skript:

import aspose_pdf
print("aspose_pdf OK")

Steg 2: Importera nödvändiga klasser

Importera Document för att hålla PDF-filen, plus annoteringsklasserna du kommer att använda för att skapa och inspektera annotationer:

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

Steg 3: Lägg till en annotation på en sida

Varje Page exponerar sina annotationer via egenskapen annotations, en AnnotationCollection. Anropa add(subtype, rect, contents) med ett subtypnamn, en (left, bottom, right, top) rektangel och annotationens textinnehåll. Standard markup-subtyper såsom "Highlight" returneras som en MarkupAnnotation instans:

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

Steg 4: Skapa annotationer från enum-subtyper

AnnotationType enumererar varje standard PDF-annotation subtyp (PDF 32000-1:2008, Tabell 169), så du kan skicka en enum-medlem istället för en rå sträng. Typ-specifik data — såsom en polygons hörn — placeras i properties dict och läses tillbaka med 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]

Steg 5: Läs och iterera befintliga annotationer

AnnotationCollection är itererbar, så du kan gå igenom varje annotation som redan finns på en sida — inklusive de som laddats från en befintlig PDF — och läsa de gemensamma egenskaperna som varje Annotation exponerar (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)

Steg 6: Generera annoteringens utseendeströmmar

En annotering som skapats utan ett explicit appearance_normal har ingen synlig rendering (/AP /N) förrän en genereras. Anropa generate_appearance(force) på en enskild Annotation, eller generate_appearances(force) på hela AnnotationCollection för att syntetisera varje saknad utseendeström på sidan på en gång:

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

Steg 7: Skilj mellan annoteringssubklasser

AnnotationCollection.add() dirigerar till en specifik subklass baserat på subtypen: markup-stil subtyper (Highlight, Square, Stamp och liknande) returneras som MarkupAnnotation, och "Link" returneras som LinkAnnotation. Båda ärver alla metoder och egenskaper från Annotation, så isinstance-kontroller låter dig grena efter annoteringstyp utan att inspektera subtype-strängar direkt:

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

Vanliga problem och lösningar

get_property returns None för en egenskap jag just har satt

properties-nycklar är exakta, skiftlägeskänsliga PDF-fältnamn ("Vertices", "Name" och liknande) — ett stavfel eller felaktigt skiftläge ignoreras tyst istället för att ge ett fel. Skicka ett default-argument till get_property(name, default) och kontrollera det explicit när du felsöker en ny subtyp.

generate_appearance() returns False

Inte varje subtyp- och egenskapskombination kan syntetiseras till en appearance-ström av den inbyggda generatorn. Kontrollera has_appearance innan du antar att anropet lyckades, och leverera en förrenderad appearance_normal (bytes) direkt på add() för de subtyper som generatorn inte täcker.

Oväntad annotation-subklass efter add()

Subtype-strängen (eller AnnotationType-medlemmen) du skickar bestämmer den returnerade klassen: markup-subtyper returneras som MarkupAnnotation, "Link" returneras som LinkAnnotation, och alla andra igenkända subtyper returneras som bas-Annotation. Använd isinstance() mot MarkupAnnotation/LinkAnnotation snarare än att anta en specifik subtype-sträng.

AnnotationFlags värden verkar inte ändra rendering

AnnotationFlags (PRINT, HIDDEN, NO_ZOOM, READ_ONLY och liknande) är en standard Python IntFlag enum för att komponera och tolka en annoterings beteendebitar med |-operatorn — det är en värdetyp, inte en egenskap som Annotation.add() skriver automatiskt. Kombinera de flaggor du behöver och skicka dem via samma typ-specifika properties-mekanism som används för annan subtype-specifik data.

Arbeta med en sida som ännu inte har några annotationer

page.annotations är alltid en giltig (möjligen tom) AnnotationCollection — du behöver aldrig kontrollera None innan du anropar add(), itererar eller anropar clear().

Vanliga frågor

Vilka annoteringssubtyper stöder Aspose.PDF FOSS för Python?

AnnotationType räknar upp alla 25 standard PDF 32000-1:2008 Tabell 169-subtyper, inklusive TEXT, LINK, FREE_TEXT, LINE, SQUARE, CIRCLE, POLYGON, HIGHLIGHT, STAMP, INK, FILE_ATTACHMENT, REDACT och mer.

Stöder detta bibliotek 3D-annoteringar?

Ja. PDF3DAnnotation, tillsammans med PDF3DArtwork, PDF3DContent, PDF3DView, PDF3DLightingScheme, och PDF3DRenderMode, modellerar en minimal PDF 3D annotation-yta (en rektangel, inbäddad grafik och namngivna vyer) för förhandsutgåva PDF 3D arbetsflöden. Se den PDF3DAnnotation-referens för dess fullständiga egenskapsuppsättning.

Hur tar jag bort en annotering från en sida?

Anropa page.annotations.delete(index) för att ta bort en annotering efter position, eller page.annotations.clear() för att ta bort alla annoteringar på sidan.

Kan jag infoga en annotering på en specifik position istället för att lägga till den?

Ja — AnnotationCollection.insert(index, subtype, rect, contents, title, appearance_normal, properties) tar samma argument som add() plus mål index.

Hur representeras en annoterings färg?

Egenskapen color på Annotation (och dess underklasser) är en tuple[float, ...] som matchar PDF /C postens komponentantal (tom när färgen inte är satt) — inte ett dedikerat färgobjekt.

Se även

 Svenska