Hoe te werken met PDF-annotaties in Python
Aspose.PDF FOSS voor Python maakt elke annotatie op een pagina beschikbaar als een live Annotation object via de AnnotationCollection van de pagina, zodat je markup-, link- en 3D-annotaties kunt toevoegen, hun type-specifieke eigenschappen kunt inspecteren en de appearance-streams kunt genereren die PDF-viewers nodig hebben om ze weer te geven — alles vanuit pure Python. Deze gids laat zien hoe je de bibliotheek installeert, annotaties toevoegt, ze weer uitleest en hun appearance-streams genereert.
Stap-voor-stap gids
Stap 1: Installeer het pakket
Installeer het Aspose.PDF FOSS-pakket:
git clone https://github.com/aspose-pdf-foss/Aspose-PDF-FOSS-for-Python.git
cd Aspose-PDF-FOSS-for-Python
pip install -e .Verifieer de installatie door de top-level aspose_pdf module te importeren, die de Document klasse blootlegt die in de onderstaande stappen wordt gebruikt. Het fragment drukt aspose_pdf OK af wanneer de import slaagt; een ModuleNotFoundError betekent meestal dat het pakket in een andere Python-omgeving is geïnstalleerd dan die waarin je script wordt uitgevoerd:
import aspose_pdf
print("aspose_pdf OK")Stap 2: Vereiste klassen importeren
Importeer Document om de PDF vast te houden, plus de annotatieklassen die je zult gebruiken om annotaties te maken en te inspecteren:
from aspose_pdf import Document
from aspose_pdf.annotations import (
Annotation,
AnnotationType,
AnnotationFlags,
MarkupAnnotation,
LinkAnnotation,
)Stap 3: Een annotatie aan een pagina toevoegen
Elke Page geeft zijn annotaties weer via de annotations eigenschap, een AnnotationCollection. Roep add(subtype, rect, contents) aan met een subtype-naam, een (left, bottom, right, top) rechthoek, en de tekstinhoud van de annotatie. Standaard markup-subtypes zoals "Highlight" worden geretourneerd als een MarkupAnnotation instantie:
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 clauseStap 4: Annotaties maken vanuit enum-subtypes
AnnotationType somt elk standaard PDF-annotatiesubtype op (PDF 32000-1:2008, Tabel 169), zodat je een enum-lid kunt doorgeven in plaats van een ruwe string. Typespecifieke gegevens — zoals de hoekpunten van een veelhoek — worden geplaatst in het properties dict en worden weer uitgelezen met 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]Stap 5: Bestaande annotaties lezen en itereren
AnnotationCollection is iterabel, zodat je elke annotatie die al op een pagina aanwezig is — inclusief die geladen uit een bestaande PDF — kunt doorlopen en de gemeenschappelijke eigenschappen kunt lezen die elke Annotation blootlegt (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)Stap 6: Genereer annotatie-verschijningsstreams
Een annotatie die zonder een expliciete appearance_normal is gemaakt, heeft geen zichtbare weergave (/AP /N) totdat er één wordt gegenereerd. Roep generate_appearance(force) aan op een enkele Annotation, of generate_appearances(force) op de hele AnnotationCollection om alle ontbrekende verschijningsstreams op de pagina in één keer te synthetiseren:
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)")Stap 7: Onderscheid annotatie-subklassen
AnnotationCollection.add() stuurt door naar een specifieke subklasse op basis van de sub-type: markup-stijl subtypes (Highlight, Square, Stamp, en soortgelijke) komen terug als MarkupAnnotation, en "Link" komt terug als LinkAnnotation. Beide erven elke methode en eigenschap van Annotation, dus isinstance controles laten je takken op annotatietype zonder direct subtype strings te inspecteren:
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)) # TrueVeelvoorkomende problemen en oplossingen
get_property returns None voor een eigenschap die ik zojuist heb ingesteld
properties sleutels zijn exacte, hoofdlettergevoelige PDF-veldnamen ("Vertices", "Name", en soortgelijke) — een typefout of verkeerde hoofdletter wordt stilletjes genegeerd in plaats van een fout te veroorzaken. Geef een default argument door aan get_property(name, default) en controleer het expliciet tijdens het debuggen van een nieuw subtype.
generate_appearance() returns False
Niet elke subtype- en eigenschapscombinatie kan door de ingebouwde generator worden gesynthetiseerd tot een appearance-stream. Controleer has_appearance voordat u aanneemt dat de oproep geslaagd is, en lever een vooraf gerenderde appearance_normal (bytes) direct op add() voor subtypes die de generator niet dekt.
Onverwachte annotatie-subklasse na add()
De subtype-string (of AnnotationType-lid) die u doorgeeft bepaalt de geretourneerde klasse: markup-subtypes komen terug als MarkupAnnotation, "Link" komt terug als LinkAnnotation, en elke andere herkende subtype komt terug als de basis Annotation. Gebruik isinstance() tegen MarkupAnnotation/LinkAnnotation in plaats van een specifieke subtype-string aan te nemen.
AnnotationFlags waarden lijken de weergave niet te wijzigen
AnnotationFlags (PRINT, HIDDEN, NO_ZOOM, READ_ONLY en soortgelijke) is een standaard Python IntFlag enum voor het samenstellen en interpreteren van de gedragsbits van een annotatie met de |-operator — het is een waardetype, geen eigenschap die Annotation.add() automatisch schrijft. Combineer de vlaggen die u nodig heeft en geef ze door via hetzelfde type-specifieke properties-mechanisme dat wordt gebruikt voor andere subtype-specifieke gegevens.
Werken met een pagina die nog geen annotaties heeft
page.annotations is altijd een geldige (mogelijk lege) AnnotationCollection — u hoeft nooit te controleren op None voordat u add() aanroept, itereert, of clear() aanroept.
Veelgestelde vragen
Welke annotatie-subtypes ondersteunt Aspose.PDF FOSS voor Python?
AnnotationType somt alle 25 standaard PDF 32000-1:2008 Tabel 169 subtypes op, waaronder TEXT, LINK, FREE_TEXT, LINE, SQUARE, CIRCLE, POLYGON, HIGHLIGHT, STAMP, INK, FILE_ATTACHMENT, REDACT en meer.
Ondersteunt deze bibliotheek 3D-annotaties?
Ja. PDF3DAnnotation, samen met PDF3DArtwork, PDF3DContent, PDF3DView, PDF3DLightingScheme, en PDF3DRenderMode, modelleert een minimale PDF 3D-annotatie-oppervlakte (een rechthoek, ingesloten artwork en benoemde weergaven) voor prerelease PDF 3D-workflows. Zie de PDF3DAnnotation-referentie voor de volledige set eigenschappen.
Hoe verwijder ik een annotatie van een pagina?
Roep page.annotations.delete(index) aan om één annotatie op positie te verwijderen, of page.annotations.clear() om alle annotaties op de pagina te verwijderen.
Kan ik een annotatie op een specifieke positie invoegen in plaats van deze toe te voegen?
Ja — AnnotationCollection.insert(index, subtype, rect, contents, title, appearance_normal, properties) neemt dezelfde argumenten als add() plus het doel index.
Hoe wordt de kleur van een annotatie weergegeven?
De color eigenschap op Annotation (en zijn subklassen) is een tuple[float, ...] die overeenkomt met het componentenaantal van de PDF /C entry (leeg wanneer de kleur niet is ingesteld) — geen toegewijd kleurobject.