💡 Esempio completo funzionante disponibile su GitHub:
extract-annotations-from-pdf-using-groupdocs-parser-dotnet
Introduzione
Un PDF che è stato revisionato di solito contiene più del suo testo visibile – note adesive, osservazioni evidenziate e commenti in linea lasciati dai revisori. Scorrere ogni pagina per trovarli non è pratico una volta che un documento ha attraversato diversi cicli di feedback. GroupDocs.Parser è una libreria .NET che legge programmaticamente le annotazioni incorporate in un documento, trasformando i commenti sparsi dei revisori in dati strutturati su cui il tuo codice può operare. Questo tutorial mostra come estrarre le annotazioni da un intero PDF, suddividerle pagina per pagina, estrarle insieme al testo del documento e esportare i risultati in CSV o JSON.
Mi sono imbattuto in questo problema mentre costruivo un tracker di revisione per un team di documentazione: una nota di rilascio di 40 pagine era passata attraverso tre revisori, e aprire manualmente il file per trovare ogni commento richiedeva più tempo di quello necessario per correggere i problemi segnalati. Estrarre le annotazioni in poche righe di codice ha trasformato l’operazione in un compito di due minuti.
Nelle sezioni seguenti imparerai a:
- Estrarre ogni annotazione da un PDF in un’unica passata.
- Etichettare ogni annotazione con la pagina a cui appartiene.
- Unire il testo del documento e il testo delle annotazioni in una singola lettura.
- Serializzare i risultati in CSV o JSON per strumenti a valle.
Perché l’estrazione delle annotazioni PDF è importante
Leggere le annotazioni PDF programmaticamente è utile per:
- Flussi di revisione: raccogliere ogni commento del revisore senza aprire il file in un visualizzatore PDF.
- Collaborazione: evidenziare sezioni annotate o annotate direttamente nei propri strumenti.
- Audit: mantenere una traccia delle marcature lasciate su un documento nel tempo, anche dopo che è stato appiattito o finalizzato.
GroupDocs.Parser ha aggiunto l’estrazione nativa delle annotazioni per i documenti PDF nella versione 26.7 tramite il metodo GetAnnotations, insieme a una nuova opzione IncludeAnnotations su TextOptions per includere il testo delle annotazioni in una lettura di testo normale.
Prerequisiti
- .NET 6.0 o successivo
- GroupDocs.Parser per .NET 26.7+ (licenza temporanea)
- Un file PDF con annotazioni esistenti (ad es.,
document-with-annotations.pdf)
Installa tramite NuGet:
dotnet add package GroupDocs.Parser
Come estrarre le annotazioni da un documento PDF?
Risposta: Carica il file con Parser, quindi chiama GetAnnotations() per l’intero documento o GetAnnotations(pageIndex) per una singola pagina. Ogni risultato è una raccolta di oggetti AnnotationItem il cui campo Value contiene il testo del commento. Se preferisci vedere i commenti in linea con il contenuto regolare del documento, imposta IncludeAnnotations su TextOptions e chiama GetText invece.
Estrarre l’intero documento
Il frammento seguente estrae ogni annotazione dal file in una singola chiamata, il modo più veloce per verificare se un documento contiene commenti aperti.
// 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;
Punti chiave:
GetAnnotations()restituiscenullquando l’estrazione delle annotazioni non è supportata per il documento, e una collezione vuota quando il documento semplicemente non ne contiene.- Ogni
AnnotationItemespone il suo testo tramite la proprietàValue– è l’unico dato che l’SDK attualmente fornisce. - Qui non è inclusa alcuna attribuzione di pagina; usa il sovraccarico per pagina mostrato di seguito se ti serve.
Estrarre per pagina
Quando la posizione di un commento è importante, itera sulle pagine del documento e chiama GetAnnotations(pageIndex) per ciascuna.
// 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;
Punti chiave:
GetDocumentInfo().PageCountguida il ciclo; non esiste un “conteggio pagine delle annotazioni” separato.GetAnnotations(pageIndex)utilizza un indice a base zero, coerente con tutti gli altri metodi a livello di pagina dell’API.- L’elenco risultante di
AnnotationRecordha esattamente la forma necessaria per un’esportazione CSV o JSON.
Estrarre il testo insieme alle annotazioni
Invece di due passaggi sul documento, puoi incorporare direttamente il testo delle annotazioni nell’output dell’estrazione del testo normale.
// 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;
}
}
Punti chiave:
IncludeAnnotationsè una proprietà diTextOptions, quindi funziona con la stessa chiamataGetTextche useresti per l’estrazione del solo testo.- Utile quando desideri un unico output in stile trascrizione anziché un elenco separato di commenti.
- Combinalo con
GetText(pageIndex, options)se ti serve solo per una pagina.
Verificare prima il supporto alle annotazioni
Non tutti i formati supportano le annotazioni, quindi è opportuno controllare prima di costruire logica attorno a GetAnnotations.
// Returns true if the loaded document format supports annotation extraction
using (var parser = new Parser(path))
{
return parser.Features.Annotations;
}
Punti chiave:
Features.Annotationsè un semplice flag booleano sull’istanzaParser.- Verificarlo in anticipo rende l’intento esplicito, anche se
GetAnnotationsrestituisce giànullin caso di fallimento.
Esportare le annotazioni in CSV
Un’esportazione CSV consente ai revisori di aprire l’elenco dei commenti direttamente in Excel. Il metodo qui sotto scrive un file a due colonne (page,value) dai record etichettati per pagina creati in precedenza.
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());
Punti chiave:
CsvEscapeaggiunge le virgolette ai campi contenenti virgole, virgolette o interruzioni di riga.- Il file risultante si apre direttamente in Excel o può essere inviato a uno strumento di ticketing.
Helper: CsvEscape
if (string.IsNullOrEmpty(s)) return string.Empty;
if (s.Contains(",") || s.Contains("\"") || s.Contains("\n"))
{
return "\"" + s.Replace("\"", "\"\"") + "\"";
}
return s;
Esportare le annotazioni in JSON
Per pipeline che consumano i commenti programmaticamente, un array JSON è solitamente più adatto di un CSV piatto.
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());
Punti chiave:
- L’output è un array piatto di oggetti
{ page, value }– facile da deserializzare per qualsiasi servizio a valle. Escapemantiene il payload JSON valido senza introdurre una libreria di serializzazione.
Helper: Escape
return s?.Replace("\\", "\\\\").Replace("\"", "\\\"") ?? string.Empty;
Confronto dei metodi: quando usare ciascuno
| Metodo | Ideale per | Vantaggi principali | Limitazioni |
|---|---|---|---|
| Estrarre l’intero documento | Verifica rapida “ci sono commenti?” | Chiamata singola, codice più semplice | Nessuna attribuzione di pagina |
| Estrarre per pagina | Instradare il feedback alla sezione corretta | Risultati con etichetta di pagina, pronti per l’esportazione | Una chiamata extra per pagina |
| Testo combinato + annotazioni | Trascrizione leggibile unica | Nessun secondo passaggio sul documento | I commenti non sono separati dal testo principale |
| Esportazione CSV | Tracciamento basato su foglio di calcolo | Facile da aprire in Excel, leggibile da umano | Struttura piatta limitata |
| Esportazione JSON | Pipeline automatizzate, sistemi di ticketing | Strutturato, leggibile da macchina | Payload leggermente più grande |
Inizia con l’estrazione dell’intero documento per confermare che un file contenga commenti da gestire, poi passa all’estrazione per pagina quando devi indirizzare il feedback a una sezione specifica.
Best practice e consigli
- Rilascia
Parsersubito: avvolgilo in un bloccousingper liberare le risorse native. - Distinguere
nullda vuoto:GetAnnotationsche restituiscenullindica che il formato non è supportato; una collezione vuota significa che il documento non ha commenti. - Controlla
Features.Annotationsnei job batch: salta i file non supportati subito, invece di affidarti a un controllonullpiù in profondità nel ciclo. - Riutilizza l’elenco etichettato per pagina: costruiscilo una volta con
ExtractAnnotationsByPagee alimenta sia l’esportatore CSV che quello JSON dallo stesso set di dati, così i due output non divergono mai. - Sicurezza: il testo delle annotazioni è input libero del revisore – trattalo come qualsiasi altra stringa non attendibile prima di renderizzarlo in UI o report.
Conclusione
GroupDocs.Parser ti offre un modo diretto e programmatico per estrarre i commenti dei revisori da un PDF, evitando la ricerca manuale. Estrarre le annotazioni per l’intero documento, etichettarle per pagina o inserirle nel flusso di testo regolare ti permette di costruire flussi di revisione che mostrano il feedback non appena il documento entra nella tua pipeline. Esporta i risultati in CSV o JSON e collegali direttamente agli strumenti già in uso dal tuo team.
Passi successivi:
- Esplora la riferimento API GetAnnotations per la firma completa del metodo e i sovraccarichi.
- Scopri come estrarre il testo da documenti PDF insieme alle annotazioni per una pipeline di contenuto completa.
- Dai un’occhiata ai progetti di esempio su GitHub per scenari di elaborazione batch (Repository di esempi).