💡 Voll funktionsfähiges Beispiel auf GitHub verfügbar:
extract-annotations-from-pdf-using-groupdocs-parser-dotnet
Einführung
Ein PDF, das bereits einer Durchsicht unterzogen wurde, enthält meist mehr als nur den sichtbaren Text – Haftnotizen, hervorgehobene Anmerkungen und Inline‑Kommentare der Reviewer. Durch jede Seite zu scrollen, um sie zu finden, skaliert nicht, sobald ein Dokument mehrere Feedback‑Runden durchlaufen hat. GroupDocs.Parser ist eine .NET‑Bibliothek, die eingebettete Anmerkungen eines Dokuments programmgesteuert ausliest und verstreute Reviewer‑Kommentare in strukturierte Daten umwandelt, mit denen Ihr Code arbeiten kann. Dieses Tutorial zeigt, wie man Anmerkungen aus einem gesamten PDF extrahiert, sie seitenweise aufschlüsselt, sie zusammen mit dem Dokumententext ausliest und die Ergebnisse nach CSV oder JSON exportiert.
Ich stieß auf dieses Problem, als ich einen Review‑Tracker für ein Dokumentationsteam entwickelte: Ein 40‑seitiges Release‑Note war durch drei Reviewer gegangen, und das manuelle Öffnen der Datei, um jeden Kommentar zu finden, dauerte länger als das eigentliche Beheben der von ihnen markierten Probleme. Das Extrahieren der Anmerkungen in wenigen Code‑Zeilen verwandelte das in einen zweiminütigen Job.
In den folgenden Abschnitten lernen Sie, wie Sie:
- Jede Anmerkung aus einem PDF in einem Durchlauf extrahieren.
- Jede Anmerkung mit der zugehörigen Seite versehen.
- Dokumententext und Anmerkungstext gemeinsam in einem einzigen Lesevorgang erhalten.
- Die Ergebnisse nach CSV oder JSON serialisieren, um sie in nachgelagerten Tools zu verwenden.
Warum das Extrahieren von PDF-Anmerkungen wichtig ist
Das programmgesteuerte Auslesen von PDF‑Anmerkungen ist nützlich für:
- Review‑Workflows: Sammeln Sie jede Reviewer‑Kommentar, ohne die Datei in einem PDF‑Viewer zu öffnen.
- Zusammenarbeit: Stellen Sie hervorgehobene oder notierte Abschnitte direkt in Ihren eigenen Tools dar.
- Auditing: Bewahren Sie einen Verlauf der Markierungen, die im Laufe der Zeit auf ein Dokument gesetzt wurden, selbst nachdem es flachgelegt oder finalisiert wurde.
GroupDocs.Parser hat die native Anmerkungs‑Extraktion für PDF‑Dokumente in Version 26.7 über die Methode GetAnnotations eingeführt, zusammen mit einer neuen IncludeAnnotations‑Option bei TextOptions, um Anmerkungstext in einen regulären Text‑Read zu übernehmen.
Voraussetzungen
- .NET 6.0 oder höher
- GroupDocs.Parser für .NET 26.7+ (temporäre Lizenz)
- Eine PDF‑Datei mit vorhandenen Anmerkungen (z. B.
document-with-annotations.pdf)
Installation via NuGet:
dotnet add package GroupDocs.Parser
Wie extrahiere ich Anmerkungen aus einem PDF-Dokument?
Antwort: Laden Sie die Datei mit Parser und rufen Sie dann GetAnnotations() für das gesamte Dokument oder GetAnnotations(pageIndex) für eine einzelne Seite auf. Jeder Rückgabewert ist eine Sammlung von AnnotationItem‑Objekten, deren Value‑Eigenschaft den Kommentartext enthält. Wenn Sie Kommentare lieber inline mit dem regulären Dokumentinhalt sehen möchten, setzen Sie IncludeAnnotations bei TextOptions und rufen stattdessen GetText auf.
Extraktion des gesamten Dokuments
Das folgende Snippet holt jede Anmerkung aus der Datei in einem einzigen Aufruf – die schnellste Methode, um zu prüfen, ob ein Dokument überhaupt offene Kommentare enthält.
// Extract every annotation from the whole document
var result = new List<string>();
using (var parser = new Parser(path))
{
IEnumerable<AnnotationItem> annotations = parser.GetAnnotations();
if (annotations == null)
{
return result; // format doesn't support annotations
}
foreach (var item in annotations)
{
result.Add(item.Value); // annotation text
}
}
return result;
Wichtige Punkte:
GetAnnotations()liefertnull, wenn die Anmerkungs‑Extraktion für das Dokument nicht unterstützt wird, und eine leere Sammlung, wenn das Dokument schlicht keine Anmerkungen enthält.- Jeder
AnnotationItemgibt seinen Text über dieValue‑Eigenschaft zurück – das ist derzeit der einzige vom SDK gemeldete Datenpunkt. - Eine Seitenzuordnung fehlt hier; verwenden Sie die per‑Seite‑Überladung unten, falls Sie diese benötigen.
Extraktion pro Seite
Wenn der Ort einer Anmerkung wichtig ist, iterieren Sie über die Seiten des Dokuments und rufen für jede GetAnnotations(pageIndex) auf.
// Tag each annotation with its zero-based page index
var result = new List<AnnotationRecord>();
using (var parser = new Parser(path))
{
if (!parser.Features.Annotations)
{
return result;
}
var info = parser.GetDocumentInfo();
if (info == null || info.PageCount == 0)
{
return result;
}
for (int pageIndex = 0; pageIndex < info.PageCount; pageIndex++)
{
IEnumerable<AnnotationItem> pageAnnotations = parser.GetAnnotations(pageIndex);
if (pageAnnotations == null)
{
continue;
}
foreach (var item in pageAnnotations)
{
result.Add(new AnnotationRecord { PageIndex = pageIndex, Value = item.Value });
}
}
}
return result;
Wichtige Punkte:
GetDocumentInfo().PageCountsteuert die Schleife; es gibt keinen separaten „Anmerkungs‑Seiten‑Count“.GetAnnotations(pageIndex)verwendet einen nullbasierten Index, analog zu allen anderen seitenbezogenen Methoden der API.- Die resultierende
AnnotationRecord‑Liste hat exakt das Format, das ein CSV‑ oder JSON‑Export benötigt.
Text zusammen mit Anmerkungen extrahieren
Anstatt das Dokument zweimal zu durchlaufen, können Sie den Anmerkungstext direkt in die reguläre Text‑Extraktion einfließen lassen.
// Read document text with annotation text included
using (var parser = new Parser(path))
{
var options = new TextOptions
{
IncludeAnnotations = true
};
using (TextReader reader = parser.GetText(options))
{
return reader?.ReadToEnd() ?? string.Empty;
}
}
Wichtige Punkte:
IncludeAnnotationsist eine Eigenschaft vonTextOptions, sodass dies mit demselbenGetText‑Aufruf funktioniert, den Sie bereits für die reine Textextraktion nutzen.- Praktisch, wenn Sie eine einzige transkript‑artige Ausgabe statt einer separaten Kommentarliste wünschen.
- Kombinieren Sie es mit
GetText(pageIndex, options), falls Sie das nur für eine Seite benötigen.
Vorabprüfung der Anmerkungsunterstützung
Nicht jedes Format unterstützt Anmerkungen, daher ist es sinnvoll, dies zu prüfen, bevor Sie Logik um GetAnnotations herum bauen.
// Returns true if the loaded document format supports annotation extraction
using (var parser = new Parser(path))
{
return parser.Features.Annotations;
}
Wichtige Punkte:
Features.Annotationsist ein einfacher boolescher Schalter auf derParser‑Instanz.- Das Vorab‑Checken macht die Absicht explizit, obwohl
GetAnnotationsbereits graceful mitnullzurückkehrt.
Exportieren der Anmerkungen nach CSV
Ein CSV‑Export ermöglicht es Reviewern, die Kommentarliste direkt in Excel zu öffnen. Die Methode unten schreibt eine zweispaltige Datei (page,value) aus den zuvor erstellten, seitengetaggten Datensätzen.
var sb = new StringBuilder();
sb.AppendLine("page,value");
foreach (var record in records)
{
sb.AppendLine($"{record.PageIndex},{CsvEscape(record.Value)}");
}
File.WriteAllText(outputPath, sb.ToString());
Wichtige Punkte:
CsvEscapesetzt Felder, die Kommas, Anführungszeichen oder Zeilenumbrüche enthalten, korrekt in Anführungszeichen.- Die resultierende Datei lässt sich direkt in Excel öffnen oder in ein Ticket‑System einspeisen.
Hilfsfunktion: CsvEscape
if (string.IsNullOrEmpty(s)) return string.Empty;
if (s.Contains(",") || s.Contains("\"") || s.Contains("\n"))
{
return "\"" + s.Replace("\"", "\"\"") + "\"";
}
return s;
Exportieren der Anmerkungen nach JSON
Für Pipelines, die Kommentare programmgesteuert verarbeiten, ist ein JSON‑Array meist besser geeignet als ein flaches CSV.
var sb = new StringBuilder();
sb.AppendLine("[");
for (int i = 0; i < records.Count; i++)
{
var comma = i < records.Count - 1 ? "," : string.Empty;
sb.AppendLine($" {{ \"page\": {records[i].PageIndex}, \"value\": \"{Escape(records[i].Value)}\" }}{comma}");
}
sb.AppendLine("]");
File.WriteAllText(outputPath, sb.ToString());
Wichtige Punkte:
- Die Ausgabe ist ein flaches Array von
{ page, value }‑Objekten – leicht von jedem nachgelagerten Service zu deserialisieren. Escapehält das Payload gültig JSON, ohne dass eine Serialisierungs‑Bibliothek eingebunden werden muss.
Hilfsfunktion: Escape
return s?.Replace("\\", "\\\\").Replace("\"", "\\\"") ?? string.Empty;
Vergleich der Methoden: Wann welche verwenden
| Methode | Am besten für | Wesentliche Vorteile | Einschränkungen |
|---|---|---|---|
| Extraktion des gesamten Dokuments | Schnelle Prüfung, ob überhaupt Kommentare vorhanden sind | Ein Aufruf, einfachster Code | Keine Seitenzuordnung |
| Extraktion pro Seite | Feedback der richtigen Abschnitt zuordnen | Seitengetaggte Ergebnisse, sofort exportbereit | Ein zusätzlicher Aufruf pro Seite |
| Text zusammen mit Anmerkungen | Ein lesbares Gesamtdokument erstellen | Kein zweiter Durchlauf über das Dokument | Kommentare sind nicht vom Fließtext getrennt |
| CSV Export | Tabellenbasierte Review‑Verfolgung | Leicht in Excel zu öffnen, menschenlesbar | Auf flache Struktur beschränkt |
| JSON Export | Automatisierte Pipelines, Ticket‑Systeme | Strukturiert, maschinenlesbar | Etwas größerer Payload |
Beginnen Sie mit der Extraktion des gesamten Dokuments, um zu bestätigen, dass eine Datei Kommentare enthält, die bearbeitet werden müssen, und wechseln Sie dann zur seitenbezogenen Extraktion, sobald Sie das Feedback einem bestimmten Abschnitt zuordnen müssen.
Best Practices und Tipps
- Parser sofort freigeben: In einem
using‑Block einbetten, um native Ressourcen zu räumen. - Unterscheiden Sie
nullvon leer:GetAnnotationsliefertnull, wenn das Format nicht unterstützt wird; eine leere Sammlung bedeutet, das Dokument hat keine Kommentare. - Prüfen Sie
Features.Annotationsin Batch‑Jobs: Nicht‑unterstützte Dateien frühzeitig überspringen, anstatt tief im Loop aufnullzu prüfen. - Wiederverwenden Sie die seitengetaggte Liste: Einmal mit
ExtractAnnotationsByPageerzeugen und sowohl CSV‑ als auch JSON‑Exporter daraus speisen, damit die beiden Ausgaben nie auseinanderdriften. - Sicherheit: Anmerkungstext ist freier Input von Reviewern – behandeln Sie ihn wie jede andere untrusted Zeichenkette, bevor Sie ihn in einer UI oder einem Bericht rendern.
Fazit
GroupDocs.Parser bietet Ihnen einen direkten, programmgesteuerten Weg, Reviewer‑Kommentare aus einem PDF zu holen, anstatt sie manuell zu suchen. Durch das Extrahieren von Anmerkungen für das gesamte Dokument, das Taggen nach Seite oder das Einbinden in den regulären Text‑Stream können Sie Review‑Workflows bauen, die Feedback sofort sichtbar machen, sobald ein Dokument in Ihre Pipeline gelangt. Exportieren Sie die Ergebnisse nach CSV oder JSON und binden Sie sie direkt in die Tools ein, die Ihr Team bereits nutzt.
Nächste Schritte:
- Erkunden Sie die GetAnnotations API‑Referenz für die vollständige Methodensignatur und Überladungen.
- Lernen Sie, wie Sie Text aus PDF‑Dokumenten extrahieren zusammen mit Anmerkungen für eine komplette Content‑Pipeline.
- Werfen Sie einen Blick auf weitere Beispielprojekte auf GitHub für Batch‑Processing‑Szenarien (Examples Repo).