💡 Tam çalışan örnek GitHub’da mevcuttur:
extract-annotations-from-pdf-using-groupdocs-parser-dotnet

Giriş

Bir PDF, incelemeden geçmiş olduğunda genellikle yalnızca görünen metninden daha fazlasını taşır – yapışkan notlar, vurgulanmış açıklamalar ve inceleyenler tarafından bırakılan satır içi yorumlar. Her sayfayı kaydırarak bunları bulmak, bir belge birkaç tur geri bildirimden geçmişse ölçeklenemez. GroupDocs.Parser, bir belgenin gömülü açıklamalarını programlı olarak okuyan bir .NET kütüphanesidir; dağınık inceleme yorumlarını, kodunuzun işleyebileceği yapılandırılmış verilere dönüştürür. Bu öğreticide, bir PDF’den tüm açıklamaları nasıl çıkaracağınızı, sayfa sayfa nasıl parçalayacağınızı, belge metniyle birlikte nasıl alacağınızı ve sonuçları CSV ya da JSON olarak dışa aktaracağınızı göstereceğiz.

Bu sorunu, bir dokümantasyon ekibi için inceleme izleyicisi oluştururken yaşadım: 40 sayfalık bir sürüm notu üç inceleyiciden geçmişti ve dosyayı manuel olarak açıp her yorumu bulmak, işaretledikleri sorunları düzeltmekten daha uzun sürüyordu. Açıklamaları birkaç satır kodla çıkarmak, işi iki dakikaya indirdi.

Aşağıdaki bölümlerde şunları öğreneceksiniz:

  • Tek bir geçişte bir PDF’den tüm açıklamaları çıkarın.
  • Her açıklamayı ait olduğu sayfa ile etiketleyin.
  • Belge metni ve açıklama metnini tek bir okuma içinde birleştirin.
  • Sonuçları CSV ya da JSON olarak serileştirerek sonraki araçlara aktarın.

PDF Açıklamalarını Çıkarma Neden Önemlidir

PDF açıklamalarını programlı olarak okumak şu durumlarda faydalıdır:

  • İnceleme iş akışları: PDF görüntüleyicide dosyayı açmadan her inceleme yorumunu toplayın.
  • İş birliği: Vurgulanan ya da not alınmış bölümleri doğrudan kendi araçlarınız içinde gösterin.
  • Denetim: Bir belge zaman içinde düzleştirildikten ya da sonlandırıldıktan sonra bile üzerindeki işaretlemelerin kaydını tutun.

GroupDocs.Parser, PDF belgeleri için yerel açıklama çıkarımını sürüm 26.7’de GetAnnotations yöntemiyle ekledi; ayrıca TextOptions üzerindeki yeni IncludeAnnotations seçeneği, açıklama metnini normal metin okumasına dahil etmeyi sağlıyor.

Önkoşullar

  • .NET 6.0 veya üzeri
  • GroupDocs.Parser for .NET 26.7+ (geçici lisans)
  • Mevcut açıklamaları olan bir PDF dosyası (ör. document-with-annotations.pdf)

NuGet üzerinden kurun:

dotnet add package GroupDocs.Parser

Bir PDF belgesinden açıklamaları nasıl çıkarırım?

Cevap: Dosyayı Parser ile yükleyin, ardından tüm belge için GetAnnotations() ya da tek bir sayfa için GetAnnotations(pageIndex) çağırın. Her sonuç, Value özelliği yorum metnini tutan AnnotationItem nesnelerinin bir koleksiyonudur. Açıklamaları belge içeriğiyle aynı satırda görmek isterseniz, TextOptions üzerindeki IncludeAnnotations özelliğini ayarlayın ve GetText çağırın.

Tüm Belge Çıkarma

Aşağıdaki kod parçacığı, dosyadan tüm açıklamaları tek bir çağrıyla çeker; bu, bir belgenin herhangi bir açık yorumu olup olmadığını kontrol etmenin en hızlı yoludur.

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

Temel noktalar:

  • GetAnnotations() belge için açıklama çıkarımı desteklenmiyorsa null döner; belge hiç açıklama içermiyorsa boş bir koleksiyon döner.
  • Her AnnotationItem metnini Value özelliği aracılığıyla sunar – SDK şu anda yalnızca bu veri noktasını raporlar.
  • Burada sayfa ataması bulunmaz; ihtiyacınız varsa aşağıdaki sayfa‑bazlı aşırı yüklemeyi kullanın.

Sayfa‑Bazlı Çıkarma

Yorumun konumu önemliyse, belgenin sayfaları üzerinde döngü kurun ve her biri için GetAnnotations(pageIndex) çağırın.

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

Temel noktalar:

  • GetDocumentInfo().PageCount döngüyü yönlendirir; ayrı bir “açıklama sayfa sayısı” yoktur.
  • GetAnnotations(pageIndex) sıfır‑tabanlı bir indeks kullanır; API’deki diğer sayfa‑seviyesi yöntemlerle aynı uyumluluğu sağlar.
  • Oluşan AnnotationRecord listesi, CSV ya da JSON dışa aktarımı için tam olarak gereken şekildedir.

Açıklamalarla Birlikte Metin Çıkarma

Belgeyi iki kez dolaşmak yerine, açıklama metnini doğrudan normal metin çıkarım çıktısına katlayabilirsiniz.

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

Temel noktalar:

  • IncludeAnnotations, TextOptions üzerindeki bir özelliktir; bu, düz metin çıkarımı için zaten kullandığınız GetText çağrısıyla aynı şekilde çalışır.
  • Tek bir transcript‑stil çıktısı istediğinizde, ayrı bir yorum listesine ihtiyaç duymadığınızda faydalıdır.
  • Sadece bir sayfa için ihtiyacınız varsa GetText(pageIndex, options) ile birleştirebilirsiniz.

Önce Açıklama Desteğini Kontrol Etme

Her format açıklamaları desteklemez; bu yüzden GetAnnotations etrafında mantık kurmadan önce kontrol etmek iyidir.

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

Temel noktalar:

  • Features.Annotations, Parser örneği üzerinde basit bir boolean bayrağıdır.
  • Önceden kontrol etmek, niyetinizi açıkça ortaya koyar; GetAnnotations zaten null döndürerek nazikçe başarısız olur.

Açıklamaları CSV’ye Dışa Aktarma

CSV dışa aktarımı, inceleyenlerin yorum listesini doğrudan Excel’de açmasını sağlar. Aşağıdaki yöntem, önceki adımda oluşturulan sayfa‑etiketli kayıtları iki sütunlu (page,value) bir dosyaya yazar.

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

Temel noktalar:

  • CsvEscape, virgül, çift tırnak ya da satır sonu içeren alanları güvenli bir şekilde tırnak içine alır.
  • Oluşan dosya doğrudan Excel’de açılır ya da bir biletleme aracına yönlendirilebilir.

Yardımcı: CsvEscape

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

Açıklamaları JSON’a Dışa Aktarma

Yorumları programlı olarak tüketen akışlar için, JSON dizisi genellikle düz CSV’den daha uygundur.

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

Temel noktalar:

  • Çıktı, { page, value } nesnelerinden oluşan düz bir dizi – herhangi bir sonraki hizmetin kolayca serileştirmesini sağlar.
  • Escape, bir serileştirme kütüphanesi eklemeden JSON geçerliliğini korur.

Yardımcı: Escape

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

Yöntemleri Karşılaştırma: Ne Zaman Hangi Yöntemi Kullanmalı

Yöntem En İyi Kullanım Durumu Temel Avantajlar Kısıtlamalar
Tüm‑Belge Çıkarma “Herhangi bir yorum var mı?” hızlı kontrolü Tek çağrı, en basit kod Sayfa ataması yok
Sayfa‑Bazlı Çıkarma Geri bildirimi doğru bölüme yönlendirme Sayfa‑etiketli sonuçlar, dışa aktarmaya hazır Sayfa başına ekstra çağrı
Metin + Açıklamalar Birleşik Tek okunabilir transcript Belgeye ikinci geçiş yok Yorumlar metinden ayrı değildir
CSV Dışa Aktarma Tablo‑tabanlı inceleme takibi Excel’de kolay açılır, insan‑okunur Düz yapı ile sınırlı
JSON Dışa Aktarma Otomatik akışlar, biletleme sistemleri Yapılandırılmış, makine‑okunur Biraz daha büyük yük

İlk olarak, bir dosyanın yorum içerip içermediğini doğrulamak için tüm‑belge çıkarımını kullanın; ardından belirli bir bölüme geri bildirimi yönlendirmeniz gerektiğinde sayfa‑bazlı çıkarıma geçin.

En İyi Uygulamalar ve İpuçları

  • Parserı hemen serbest bırakın: yerel kaynakları temizlemek için using bloğu içinde tutun.
  • null ile boş koleksiyonu ayırt edin: GetAnnotations null döndürürse format desteklenmiyordur; boş koleksiyon ise belge yorum içermiyordur.
  • Toplu işlerde Features.Annotations kontrol edin: döngünüzün içinde null kontrolüne bel bağlamadan, desteklenmeyen dosyaları erken atlayın.
  • Sayfa‑etiketli listeyi yeniden kullanın: ExtractAnnotationsByPage ile bir kez oluşturun ve CSV ile JSON dışa aktarıcılarını aynı veriden besleyin; böylece iki çıktı asla birbirinden farklılaşmaz.
  • Güvenlik: Açıklama metni serbest biçimli inceleme girdisidir – UI ya da raporda göstermeden önce diğer güvensiz stringler gibi işleyin.

Sonuç

GroupDocs.Parser, PDF’den inceleme yorumlarını elle aramak yerine doğrudan, programlı bir şekilde çekmenizi sağlar. Açıklamaları tüm belge için çıkararak, sayfa ile etiketleyerek ya da normal metin akışına katlayarak, belge pipeline’ınıza girdiği anda geri bildirimi ortaya çıkaran inceleme iş akışları oluşturabilirsiniz. Sonuçları CSV ya da JSON olarak dışa aktarın ve ekibinizin zaten kullandığı araçlara doğrudan bağlayın.

Sonraki adımlar:

Ek Kaynaklar