💡 Contoh kerja penuh tersedia di GitHub:
extract-annotations-from-pdf-using-groupdocs-parser-dotnet

Pendahuluan

PDF yang telah melalui proses review biasanya membawa lebih dari sekadar teks yang terlihat – catatan tempel, sorotan, dan komentar sebaris yang ditinggalkan oleh reviewer. Menggulung setiap halaman untuk menemukannya tidak skalabel setelah sebuah dokumen melewati beberapa putaran umpan balik. GroupDocs.Parser adalah perpustakaan .NET yang membaca anotasi tertanam dalam dokumen secara programatik, mengubah komentar reviewer yang tersebar menjadi data terstruktur yang dapat diproses oleh kode Anda. Tutorial ini menunjukkan cara mengekstrak anotasi dari seluruh PDF, memecahnya per halaman, mengambilnya bersamaan dengan teks dokumen, dan mengekspor hasilnya ke CSV atau JSON.

Saya menemui masalah ini saat membangun pelacak review untuk tim dokumentasi: catatan rilis 40 halaman telah melalui tiga reviewer, dan membuka file secara manual untuk menemukan setiap komentar memakan waktu lebih lama daripada memperbaiki masalah yang mereka tandai. Mengekstrak anotasi dalam beberapa baris kode mengubahnya menjadi pekerjaan dua menit.

Di bagian berikut Anda akan belajar cara:

  • Mengekstrak setiap anotasi dari PDF dalam satu kali proses.
  • Menandai setiap anotasi dengan halaman tempatnya berada.
  • Menggabungkan teks dokumen dan teks anotasi dalam satu pembacaan.
  • Menyerialkan hasil ke CSV atau JSON untuk alat downstream.

Mengapa Mengekstrak Anotasi PDF Penting

Membaca anotasi PDF secara programatik berguna untuk:

  • Alur kerja review: Kumpulkan setiap komentar reviewer tanpa membuka file di penampil PDF.
  • Kolaborasi: Tampilkan bagian yang disorot atau dicatat langsung di dalam alat Anda.
  • Audit: Simpan catatan markup yang ditinggalkan pada dokumen seiring waktu, bahkan setelah dokumen diratakan atau diselesaikan.

GroupDocs.Parser menambahkan ekstraksi anotasi native untuk dokumen PDF pada versi 26.7 melalui metode GetAnnotations, bersama opsi baru IncludeAnnotations pada TextOptions untuk menarik teks anotasi ke dalam pembacaan teks biasa.

Prasyarat

  • .NET 6.0 atau lebih baru
  • GroupDocs.Parser untuk .NET 26.7+ (lisensi sementara)
  • File PDF dengan anotasi yang sudah ada (misalnya, document-with-annotations.pdf)

Instal via NuGet:

dotnet add package GroupDocs.Parser

Bagaimana cara mengekstrak anotasi dari dokumen PDF?

Jawaban: Muat file dengan Parser, lalu panggil GetAnnotations() untuk seluruh dokumen atau GetAnnotations(pageIndex) untuk satu halaman. Setiap hasil adalah koleksi objek AnnotationItem yang properti Value‑nya berisi teks komentar. Jika Anda lebih suka melihat komentar bersamaan dengan konten reguler dokumen, atur IncludeAnnotations pada TextOptions dan panggil GetText sebagai gantinya.

Ekstraksi Seluruh Dokumen

Potongan kode berikut menarik setiap anotasi dari file dalam satu panggilan, yang merupakan cara tercepat untuk memeriksa apakah dokumen memiliki komentar terbuka sama sekali.

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

Poin penting:

  • GetAnnotations() mengembalikan null ketika ekstraksi anotasi tidak didukung untuk dokumen tersebut, dan mengembalikan koleksi kosong ketika dokumen memang tidak memiliki anotasi.
  • Setiap AnnotationItem mengekspos teksnya melalui properti Value – itu satu‑satunya titik data yang saat ini dilaporkan SDK.
  • Tidak ada atribusi halaman yang disertakan di sini; gunakan overload per‑halaman di bawah jika Anda membutuhkannya.

Ekstraksi Per Halaman

Ketika lokasi komentar penting, lakukan iterasi atas halaman dokumen dan panggil GetAnnotations(pageIndex) untuk masing‑masing.

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

Poin penting:

  • GetDocumentInfo().PageCount menggerakkan loop; tidak ada “jumlah halaman anotasi” terpisah.
  • GetAnnotations(pageIndex) menggunakan indeks berbasis nol, sama seperti semua metode tingkat‑halaman lainnya dalam API.
  • Daftar AnnotationRecord yang dihasilkan memiliki bentuk yang tepat untuk ekspor CSV atau JSON.

Mengekstrak Teks Bersama Anotasi

Alih‑alih dua kali proses pada dokumen, Anda dapat menyisipkan teks anotasi langsung ke dalam output ekstraksi teks reguler.

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

Poin penting:

  • IncludeAnnotations adalah properti pada TextOptions, sehingga ini bekerja dengan panggilan GetText yang sama yang sudah Anda gunakan untuk ekstraksi teks biasa.
  • Berguna ketika Anda menginginkan output gaya transkrip tunggal alih‑alih daftar komentar terpisah.
  • Gabungkan dengan GetText(pageIndex, options) jika Anda hanya memerlukannya untuk satu halaman.

Memeriksa Dukungan Anotasi Terlebih Dahulu

Tidak setiap format mendukung anotasi, jadi ada baiknya memeriksanya sebelum Anda menulis logika di sekitar GetAnnotations.

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

Poin penting:

  • Features.Annotations adalah flag boolean sederhana pada instance Parser.
  • Memeriksanya di awal membuat niat menjadi eksplisit, meskipun GetAnnotations sudah gagal secara elegan dengan mengembalikan null.

Mengekspor Anotasi ke CSV

Ekspor CSV memungkinkan reviewer membuka daftar komentar langsung di Excel. Metode di bawah menulis file dua kolom (page,value) dari catatan yang telah ditandai halaman sebelumnya.

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

Poin penting:

  • CsvEscape mengutip aman bidang yang mengandung koma, tanda kutip, atau baris baru.
  • File yang dihasilkan dapat dibuka langsung di Excel atau dipipe ke alat tiket.

Helper: CsvEscape

// Escape CSV fields containing commas, quotes, or line breaks
if (string.IsNullOrEmpty(s)) return string.Empty;
if (s.Contains(",") || s.Contains("\"") || s.Contains("\n"))
{
    return "\"" + s.Replace("\"", "\"\"") + "\"";
}
return s;

Mengekspor Anotasi ke JSON

Untuk pipeline yang mengonsumsi komentar secara programatik, array JSON biasanya lebih cocok daripada CSV datar.

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

Poin penting:

  • Output berupa array datar objek { page, value } – mudah bagi layanan downstream mana pun untuk mendeserialisasinya.
  • Escape menjaga payload tetap valid JSON tanpa harus menambahkan pustaka serialisasi.

Helper: Escape

// Escape characters for JSON string values
return s?.Replace("\\", "\\\\").Replace("\"", "\\\"") ?? string.Empty;

Membandingkan Metode: Kapan Menggunakan Masing‑Masing

Metode Terbaik Untuk Keunggulan Utama Keterbatasan
Ekstraksi Seluruh Dokumen Pemeriksaan cepat “apakah ada komentar sama sekali?” Satu panggilan, kode paling sederhana Tidak ada atribusi halaman
Ekstraksi Per Halaman Menyalurkan umpan balik ke bagian yang tepat Hasil ber‑tag halaman, siap diekspor Satu panggilan ekstra per halaman
Teks + Anotasi Gabungan Transkrip tunggal yang dapat dibaca Tidak perlu pass kedua pada dokumen Komentar tidak dipisahkan dari teks utama
Ekspor CSV Pelacakan review berbasis spreadsheet Mudah dibuka di Excel, dapat dibaca manusia Terbatas pada struktur datar
Ekspor JSON Pipeline otomatis, sistem tiket Terstruktur, dapat dibaca mesin Payload sedikit lebih besar

Mulailah dengan ekstraksi seluruh dokumen untuk memastikan file memiliki komentar yang layak diproses, kemudian beralih ke ekstraksi per halaman ketika Anda perlu menyalurkan umpan balik ke bagian tertentu.

Praktik Terbaik dan Tips

  • Dispose Parser segera: bungkus dalam blok using untuk membebaskan sumber daya native.
  • Bedakan null dari kosong: GetAnnotations mengembalikan null berarti format tidak didukung; koleksi kosong berarti dokumen tidak memiliki komentar.
  • Periksa Features.Annotations dalam pekerjaan batch: lewati file yang tidak didukung lebih awal daripada mengandalkan pemeriksaan null di dalam loop.
  • Gunakan kembali daftar ber‑tag halaman: bangun sekali dengan ExtractAnnotationsByPage dan beri makan kedua pengekspor CSV dan JSON dari data yang sama, sehingga dua output tidak pernah berbeda.
  • Keamanan: teks anotasi adalah masukan bebas reviewer – perlakukan seperti string tidak terpercaya lainnya sebelum menampilkannya di UI atau laporan.

Kesimpulan

GroupDocs.Parser memberi Anda cara langsung dan programatik untuk menarik komentar reviewer dari PDF alih‑alih mencarinya secara manual. Dengan mengekstrak anotasi untuk seluruh dokumen, menandainya per halaman, atau menyisipkannya ke dalam aliran teks reguler, Anda dapat membangun alur kerja review yang menampilkan umpan balik begitu dokumen masuk ke pipeline Anda. Ekspor hasilnya ke CSV atau JSON dan hubungkan langsung ke alat yang sudah digunakan tim Anda.

Langkah selanjutnya:

Sumber Daya Tambahan