💡 Plně funkční příklad je k dispozici na GitHubu:
extract-annotations-from-pdf-using-groupdocs-parser-dotnet

Úvod

PDF, které prošlo revizí, obvykle obsahuje více než jen viditelný text – lepkavé poznámky, zvýrazněné připomínky a vložené komentáře od recenzentů. Procházet každou stránku a hledat je se nevyplatí, jakmile dokument prošel několika koly zpětné vazby. GroupDocs.Parser je .NET knihovna, která programově čte vložené anotace dokumentu a převádí rozptýlené komentáře recenzentů na strukturovaná data, se kterými může váš kód pracovat. Tento tutoriál ukazuje, jak extrahovat anotace z celého PDF, rozdělit je po stránkách, získat je společně s textem dokumentu a exportovat výsledky do CSV nebo JSON.

Na tento problém jsem narazil při tvorbě sledovače revizí pro tým dokumentace: 40‑stránková poznámka k vydání prošla třemi recenzenty a ruční otevírání souboru a hledání každého komentáře trvalo déle, než samotné opravy, které označili. Extrahování anotací několika řádky kódu to proměnilo v dvouminutovou práci.

V následujících sekcích se naučíte:

  • Extrahovat každou anotaci z PDF v jednom průchodu.
  • Označit každou anotaci stránkou, ke které patří.
  • Získat text dokumentu a text anotace společně v jednom čtení.
  • Serializovat výsledky do CSV nebo JSON pro další nástroje.

Proč je důležité extrahovat anotace z PDF

Programatické čtení anotací PDF je užitečné pro:

  • Revizní workflow: Shromáždit každý komentář recenzenta bez otevírání souboru v PDF prohlížeči.
  • Spolupráci: Zobrazit zvýrazněné nebo poznamenané úseky přímo ve vašich nástrojích.
  • Audit: Uchovat záznam o poznámkách přidaných do dokumentu v čase, i po jeho zploštění nebo finalizaci.

GroupDocs.Parser přidal nativní extrakci anotací pro PDF dokumenty ve verzi 26.7 prostřednictvím metody GetAnnotations a novou možnost IncludeAnnotations v TextOptions pro zahrnutí textu anotací do běžného čtení textu.

Požadavky

  • .NET 6.0 nebo novější
  • GroupDocs.Parser pro .NET 26.7+ (dočasná licence)
  • PDF soubor s existujícími anotacemi (např. document-with-annotations.pdf)

Instalace přes NuGet:

dotnet add package GroupDocs.Parser

Jak extrahovat anotace z PDF dokumentu?

Odpověď: Načtěte soubor pomocí Parser a poté zavolejte GetAnnotations() pro celý dokument nebo GetAnnotations(pageIndex) pro jednotlivou stránku. Každý výsledek je kolekce objektů AnnotationItem, jejichž vlastnost Value obsahuje text komentáře. Pokud chcete vidět komentáře vložené do běžného obsahu dokumentu, nastavte IncludeAnnotations v TextOptions a místo toho zavolejte GetText.

Extrakce celého dokumentu

Následující úryvek získá každou anotaci ze souboru jedním voláním, což je nejrychlejší způsob, jak zjistit, zda dokument vůbec obsahuje otevřené komentáře.

// 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;

Klíčové body:

  • GetAnnotations() vrací null, když extrakce anotací pro dokument není podporována, a prázdnou kolekci, když dokument prostě žádné anotace nemá.
  • Každý AnnotationItem poskytuje svůj text přes vlastnost Value – to je jediný datový bod, který SDK v současnosti poskytuje.
  • Žádná informace o stránce není zahrnuta; pokud ji potřebujete, použijte níže uvedený přetížený způsob pro jednotlivé stránky.

Extrakce po stránkách

Když záleží na umístění komentáře, projděte stránky dokumentu a pro každou zavolejte GetAnnotations(pageIndex).

// 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;

Klíčové body:

  • GetDocumentInfo().PageCount řídí smyčku; neexistuje samostatný „počet stránek s anotacemi“.
  • GetAnnotations(pageIndex) používá nulový index, stejně jako všechny ostatní metody pracující se stránkami v API.
  • Výsledný seznam AnnotationRecord má přesně takový tvar, jaký potřebuje export do CSV nebo JSON.

Extrakce textu společně s anotacemi

Místo dvou průchodů dokumentem můžete vložit text anotací přímo do výstupu běžné extrakce textu.

// 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;
    }
}

Klíčové body:

  • IncludeAnnotations je vlastnost v TextOptions, takže to funguje se stejným voláním GetText, které už používáte pro čistý text.
  • Užitečné, když chcete jeden výstup ve stylu přepisu místo samostatného seznamu komentářů.
  • Kombinujte s GetText(pageIndex, options), pokud to potřebujete jen pro jednu stránku.

Kontrola podpory anotací předem

Ne každý formát podporuje anotace, proto je dobré to ověřit, než budete stavět logiku kolem GetAnnotations.

// Returns true if the loaded document format supports annotation extraction
using (var parser = new Parser(path))
{
    return parser.Features.Annotations;
}

Klíčové body:

  • Features.Annotations je jednoduchý boolean flag na instanci Parser.
  • Ověření předem dělá záměr explicitní, i když GetAnnotations už selže elegantně vrácením null.

Export anotací do CSV

Export do CSV umožní recenzentům otevřít seznam komentářů přímo v Excelu. Níže uvedená metoda zapíše dvousloupcový soubor (page,value) z dříve vytvořených záznamů s označením stránky.

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());

Klíčové body:

  • CsvEscape bezpečně uvozovku pole obsahující čárky, uvozovky nebo zalomení řádku.
  • Výsledný soubor se otevře přímo v Excelu nebo může být předán do ticketovacího nástroje.

Pomocná metoda: CsvEscape

if (string.IsNullOrEmpty(s)) return string.Empty;
if (s.Contains(",") || s.Contains("\"") || s.Contains("\n"))
{
    return "\"" + s.Replace("\"", "\"\"") + "\"";
}
return s;

Export anotací do JSON

Pro pipeline, které konzumují komentáře programově, je JSON pole obvykle vhodnější než ploché 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());

Klíčové body:

  • Výstup je ploché pole objektů { page, value } – snadno deserializovatelné libovolnou downstream službou.
  • Escape udržuje payload platný JSON bez nutnosti zavádět knihovnu pro serializaci.

Pomocná metoda: Escape

return s?.Replace("\\", "\\\\").Replace("\"", "\\\"") ?? string.Empty;

Porovnání metod: Kdy použít kterou

Metoda Nejlepší pro Klíčové výhody Omezení
Whole‑Document Extraction Rychlé zjištění „jsou vůbec nějaké komentáře?“ Jedno volání, nejjednodušší kód Žádná informace o stránce
Per‑Page Extraction Směrování zpětné vazby na správnou sekci Výsledky s označením stránky, připravené k exportu Jedno extra volání na stránku
Combined Text + Annotations Jeden čitelný přepis Žádný druhý průchod dokumentem Komentáře nejsou odděleny od těla textu
CSV Export Sledování revizí v tabulkovém procesoru Snadno otevřitelné v Excelu, čitelné pro člověka Omezeno na plochou strukturu
JSON Export Automatizované pipeline, ticketovací systémy Strukturované, strojově čitelné O něco větší payload

Začněte s extrakcí celého dokumentu, abyste potvrdili, že soubor obsahuje komentáře, které stojí za zpracování, a poté přejděte na extrakci po stránkách, pokud potřebujete směrovat zpětnou vazbu na konkrétní část.

Nejlepší postupy a tipy

  • Okamžitě uvolňujte Parser: zabalte jej do using bloku, aby se uvolnily nativní zdroje.
  • Rozlišujte null a prázdné: GetAnnotations vrací null, pokud formát není podporován; prázdná kolekce znamená, že dokument nemá žádné komentáře.
  • Kontrolujte Features.Annotations v dávkových úlohách: vynechejte nepodporované soubory hned na začátku místo spoléhaní se na null kontrolu uvnitř smyčky.
  • Znovu použijte seznam s označením stránky: vytvořte jej jednou pomocí ExtractAnnotationsByPage a použijte pro CSV i JSON exportéry ze stejných dat, aby výstupy nikdy neodchýlily.
  • Bezpečnost: text anotace je volně psaný vstup recenzenta – zacházejte s ním jako s jakýmkoli jiným nedůvěryhodným řetězcem před jeho vykreslením v UI nebo reportu.

Závěr

GroupDocs.Parser vám poskytuje přímý, programový způsob, jak vytáhnout komentáře recenzentů z PDF místo ručního hledání. Extrahováním anotací pro celý dokument, jejich označením podle stránky nebo vložením do běžného textového proudu můžete vytvořit revizní workflow, který zobrazí zpětnou vazbu okamžitě po přijetí dokumentu do vašeho pipeline. Exportujte výsledky do CSV nebo JSON a napojte je přímo na nástroje, které váš tým již používá.

Další kroky:

Další zdroje