So arbeiten Sie mit PDF-Anmerkungen in Python
Aspose.PDF FOSS für Python stellt jede Anmerkung auf einer Seite als ein lebendes Annotation-Objekt über das AnnotationCollection der Seite bereit, sodass Sie Markup-, Link- und 3D-Anmerkungen hinzufügen, deren typenspezifische Eigenschaften prüfen und die Appearance-Streams erzeugen können, die PDF-Viewer zum Rendern benötigen – alles aus reinem Python. Dieser Leitfaden zeigt, wie man die Bibliothek installiert, Anmerkungen hinzufügt, sie wieder ausliest und ihre Appearance-Streams erzeugt.
Schritt-für-Schritt-Anleitung
Schritt 1: Paket installieren
Installieren Sie das Aspose.PDF FOSS-Paket:
git clone https://github.com/aspose-pdf-foss/Aspose-PDF-FOSS-for-Python.git
cd Aspose-PDF-FOSS-for-Python
pip install -e .Überprüfen Sie die Installation, indem Sie das Top-Level-Modul aspose_pdf importieren, das die in den nachfolgenden Schritten verwendete Klasse Document bereitstellt. Das Snippet gibt aspose_pdf OK aus, wenn der Import erfolgreich ist; ein ModuleNotFoundError bedeutet in der Regel, dass das Paket in einer anderen Python-Umgebung installiert wurde als die, in der Ihr Skript ausgeführt wird:
import aspose_pdf
print("aspose_pdf OK")Schritt 2: Erforderliche Klassen importieren
Import Document zum Halten des PDFs, plus die Annotationsklassen, die Sie zum Erstellen und Untersuchen von Anmerkungen verwenden:
from aspose_pdf import Document
from aspose_pdf.annotations import (
Annotation,
AnnotationType,
AnnotationFlags,
MarkupAnnotation,
LinkAnnotation,
)Schritt 3: Eine Annotation zu einer Seite hinzufügen
Jedes Page gibt seine Anmerkungen über die annotations-Eigenschaft frei, ein AnnotationCollection. Rufen Sie add(subtype, rect, contents) mit einem Subtype-Namen, einem (left, bottom, right, top)-Rechteck und dem Textinhalt der Annotation auf. Standard-Markup-Subtypen wie "Highlight" werden als MarkupAnnotation-Instanz zurückgegeben:
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 clauseSchritt 4: Anmerkungen aus Enum-Subtypen erstellen
AnnotationType enumeriert jeden standardmäßigen PDF-Annotations-Subtype (PDF 32000-1:2008, Tabelle 169), sodass Sie ein Enum-Mitglied anstelle eines Roh-Strings übergeben können. Typspezifische Daten – wie die Eckpunkte eines Polygons – kommen in das properties-Dictionary und werden mit get_property wieder ausgelesen:
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]Schritt 5: Vorhandene Anmerkungen lesen und iterieren
AnnotationCollection ist iterierbar, sodass Sie jede bereits auf einer Seite vorhandene Annotation durchlaufen können – einschließlich solcher, die aus einem bestehenden PDF geladen wurden – und die gemeinsamen Eigenschaften lesen können, die jede Annotation bereitstellt (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)Schritt 6: Annotations-Appearance-Streams erzeugen
Eine Annotation, die ohne ein explizites appearance_normal erstellt wurde, hat keine sichtbare Darstellung (/AP /N), bis eine erzeugt wird. Rufen Sie generate_appearance(force) für ein einzelnes Annotation oder generate_appearances(force) für das gesamte AnnotationCollection auf, um alle fehlenden Appearance-Streams auf der Seite auf einmal zu erzeugen:
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)")Schritt 7: Annotations-Unterklassen unterscheiden
AnnotationCollection.add() leitet an eine spezifische Unterklasse basierend auf dem Subtyp weiter: Markup-artige Subtypen (Highlight, Square, Stamp und ähnliche) werden als MarkupAnnotation zurückgeliefert, und "Link" wird als LinkAnnotation zurückgeliefert. Beide erben alle Methoden und Eigenschaften von Annotation, sodass isinstance checks es Ihnen ermöglichen, nach Annotationsart zu verzweigen, ohne subtype-Zeichenketten direkt zu untersuchen:
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)) # TrueHäufige Probleme und Lösungen
get_property returns None für eine Eigenschaft, die ich gerade gesetzt habe
properties-Schlüssel sind exakte, case-sensitive PDF-Feldnamen ("Vertices", "Name" und ähnliche) — ein Tippfehler oder falsche Groß-/Kleinschreibung wird stillschweigend ignoriert, anstatt einen Fehler auszulösen. Übergeben Sie ein default-Argument an get_property(name, default) und prüfen Sie es explizit, während Sie einen neuen Subtyp debuggen.
generate_appearance() returns False
Nicht jede Subtyp- und Eigenschaftskombination kann vom integrierten Generator in einen Appearance-Stream synthetisiert werden. Prüfen Sie has_appearance, bevor Sie annehmen, dass der Aufruf erfolgreich war, und liefern Sie ein vorgerendertes appearance_normal (bytes) direkt auf add() für Subtypen, die der Generator nicht abdeckt.
Unerwartete Annotationsunterklasse nach add()
Der von Ihnen übergebene Subtyp-String (oder AnnotationType-Member) bestimmt die zurückgegebene Klasse: Markup-Subtypen werden als MarkupAnnotation zurückgeliefert, "Link" wird als LinkAnnotation zurückgegeben, und jeder andere erkannte Subtyp wird als die Basis-Annotation zurückgeliefert. Verwenden Sie isinstance() gegenüber MarkupAnnotation/LinkAnnotation, anstatt einen bestimmten Subtyp-String anzunehmen.
AnnotationFlags Werte scheinen die Darstellung nicht zu ändern
AnnotationFlags (PRINT, HIDDEN, NO_ZOOM, READ_ONLY und ähnliche) ist ein standardmäßiges Python IntFlag-Enum zum Zusammensetzen und Interpretieren der Verhaltensbits einer Annotation mit dem |-Operator — es ist ein Werttyp, keine Eigenschaft, die Annotation.add() automatisch schreibt. Kombinieren Sie die benötigten Flags und übergeben Sie sie über denselben typenspezifischen properties-Mechanismus, der für andere subtyp-spezifische Daten verwendet wird.
Arbeiten mit einer Seite, die noch keine Anmerkungen hat
page.annotations ist immer ein gültiges (möglicherweise leeres) AnnotationCollection — Sie müssen nie auf None prüfen, bevor Sie add() aufrufen, iterieren oder clear() aufrufen.
Häufig gestellte Fragen
Welche Annotationsuntertypen unterstützt Aspose.PDF FOSS für Python?
AnnotationType enumeriert alle 25 Standard-PDF32000-1:2008 Tabelle169 Untertypen, einschließlich TEXT, LINK, FREE_TEXT, LINE, SQUARE, CIRCLE, POLYGON, HIGHLIGHT, STAMP, INK, FILE_ATTACHMENT, REDACT und mehr.
Unterstützt diese Bibliothek 3D-Annotationen?
Ja. PDF3DAnnotation, zusammen mit PDF3DArtwork, PDF3DContent, PDF3DView, PDF3DLightingScheme, und PDF3DRenderMode, modelliert eine minimale PDF-3D-Annotationsfläche (ein Rechteck, eingebettete Grafik und benannte Ansichten) für Vorab-PDF-3D-Workflows. Siehe die PDF3DAnnotation-Referenz für seinen vollständigen Eigenschaftensatz.
Wie entferne ich eine Annotation von einer Seite?
Rufen Sie page.annotations.delete(index) auf, um eine Annotation nach Position zu entfernen, oder page.annotations.clear(), um alle Annotationen auf der Seite zu entfernen.
Kann ich eine Annotation an einer bestimmten Position einfügen, anstatt sie anzuhängen?
Ja — AnnotationCollection.insert(index, subtype, rect, contents, title, appearance_normal, properties) verwendet dieselben Argumente wie add() plus das Ziel index.
Wie wird die Farbe einer Annotation dargestellt?
Die color-Eigenschaft von Annotation (und deren Unterklassen) ist ein tuple[float, ...], das der Komponentenanzahl des PDF-/C-Eintrags entspricht (leer, wenn die Farbe nicht gesetzt ist) — kein dediziertes Farbe-Objekt.