PDFium Component, bir PDF sayfasındaki tabloları tespit eder ve bunları satır ve sütun span'leri, başlık satırları ve bir güven değerine sahip bir hücre ızgarası olarak döndürür; tek bir sayfa için ExtractTables ve tüm bir belge için ExtractDocumentTables aracılığıyla. Her tablo tek bir çağrıyla CSV veya JSON'a dönüşür ve bir sayfa sonu boyunca devam eden tablolar bir devamlılık zincirine bağlanabilir
PDF'nin bir tablo nesnesi yoktur. Bir PDF'deki bir tablo, bir insanın onları bir ızgara olarak okuyacağı şekilde konumlandırılmış, bazen etraflarına çizgiler çizilmiş, sıklıkla da çizilmemiş bir metin çalıştırmaları kümesidir. Izgarayı kurtarmak, dosyanın hiçbir zaman kaydetmediği bir niyeti yeniden inşa etmek anlamına gelir; her çıkarma aracının biraz farklı sonuçlar üretmesinin ve size güvenini söyleyen bir aracın söylemeyenden daha kullanışlı olmasının nedeni budur
İki Tablo Türü İçin İki Tespit Modu
Çizgili tespit, çizilen çizgileri kullanır. Her vurgulu yol parçası, sayfa nesnesinin matrisi aracılığıyla sayfa koordinatlarına dönüştürülür, yatay ve dikey çizgiler kesiştirilir ve kesişimler bağlı bileşenler oluşturur. Her bileşen kendi sıralanmış X ve Y konumları ızgarası haline gelir; aynı sayfadaki iki ayrı tablonun tek bir anlamsız ızgaraya birleştirilmesini önleyen şey budur
Boşluk tespiti, çizgiler yerine hizalamayla çizilen tabloları ele alır. Kelime kutuları görsel satırlara gruplandırılır, bir satır içindeki boşluklar onu aday sütunlara böler ve bir tablo yalnızca en az MinRows satır, AlignmentTolerance içinde en az MinColumns sola hizalanmış çapayı tekrarladığında kabul edilir. Satır boşluğu faktörü varsayılan olarak 3'tür; bu, birkaç metin çalıştırması içeren tek bir satırın bir tablo gibi görünmesine izin vermeden 12 puntoluk metne tipik olan yaklaşık 30 puntoluk taban çizgisi aralığını kapsar
uses
PDFium;
var
Pdf: TPdf;
Options: TPdfTableExtractionOptions;
Tables: TPdfTables;
I: Integer;
begin
Pdf := TPdf.Create(nil);
try
Pdf.FileName := 'annual-report.pdf';
Pdf.LoadDocument;
Pdf.PageNumber := 12; // 1 tabanlı
Options := TPdfTableExtractionOptions.Default;
Options.DetectRuledTables := True;
Options.DetectWhitespaceTables := True;
Options.MinConfidence := 0.6; // varsayılan 0,5'tir
Options.HeaderRowCount := 1;
Tables := Pdf.ExtractTables(Options);
for I := 0 to High(Tables) do
Writeln(Format('table %d: %dx%d cells, confidence %.2f, mode %d',
[I, Tables[I].RowCount, Tables[I].ColumnCount,
Tables[I].Confidence, Ord(Tables[I].DetectionMode)]));
if Length(Tables) > 0 then
SaveText('page12-table0.csv', Tables[0].ToCsv);
finally
Pdf.Free;
end;
end;
Birleştirilmiş Hücreler Nasıl Kurtarılır?
Bu, naif çıkarıcıların yanlış yaptığı kısımdır. Birleştirilmiş bir hücre yalnızca global ızgaradan tanımlanamaz, çünkü ızgara sayfadaki tüm çizgilerden türetilir ve birleştirilmiş bir bölge, onu ayıracak olan iç çizgiden basitçe yoksundur
Burada kullanılan kural yereldir: aralarındaki aralığı hiçbir sınır çizgisi kapsamadığında iki bitişik temel hücre birleştirilir. Union-find bunları birleştirir, ortaya çıkan dikdörtgen bileşenler RowSpan ve ColumnSpan değerleri haline gelir ve metin, merkez noktasına göre bir temel hücreye atanır ve ardından o hücreyi birleştirme köküne kadar takip eder. Bunu bu şekilde yapmak, her kelimeyi her hücreye karşı test etmekten elde edilen ikinci dereceden tarama yerine, maliyeti kelimeler artı hücrelerde doğrusal tutar
Pratik etki, üç sütuna yayılan birleştirilmiş bir "Total" başlığına sahip bir mali tablonun, bir dolu hücre ve iki gizemli boş hücre yerine span üç olan tek bir hücreyle ortaya çıkmasıdır
Sayfalar Arası Devamlılık
Uzun tablolar sayfalar arasında bölünür ve her sayfanın parçasını bağımsız bir tablo olarak ele almak, çağıranı bunları dikmeye zorlar. ExtractDocumentTables bunun yerine bunları bağlayabilir, ama yalnızca katı koşullar altında: parça, önceki sayfadaki en alttaki tablo olmalıdır, bir sonraki, sonraki sayfadaki en üstteki tablo olmalıdır, sayfa numaraları bitişik olmalıdır ve sütun sınırları eşleşmelidir
Dört koşulun tümü birlikte, bariz hatayı önleyen şeydir; bu hata, bir belgedeki her dört sütunlu tabloyu, yalnızca aynı sütun sayısını paylaştıkları için tek bir hayali mega tabloya zincirlemektir. Koşullar sağlandığında tablolar bir devamlılık grubu tanımlayıcısını paylaşır ve devamlılık meta verisi taşır; sağlanmadığında ayrı tablolar elde edersiniz ve kendiniz karar verebilirsiniz
Belge düzeyinde çıkarma, MaxCells ve MaxTables bütçelerini sayfa başına sıfırlamak yerine sayfalar arasında paylaşır ve etkin sayfayı bir finally bloğunda geri yükler, bu yüzden bir görüntüleyicide çalıştırılan bir çıkarma, kullanıcıyı bulunduğu sayfaya bakarken bırakır
Veriyi Bozmadan Dışa Aktarma
Her iki dışa aktarıcı da kaçış konusunda kasıtlıdır. CSV her zaman alanları tırnak içine alır ve iç tırnak işaretlerini ikiye katlar; bu, virgül içeren bir hücrenin sessizce iki sütuna dönüştüğü klasik başarısızlığı önler. Birleştirilmiş hücreler için içerik yalnızca sol üst çapada yayılır, bu yüzden bir CSV gidiş-dönüşü, kapladığı sütunlar boyunca yayılan bir başlığı yinelemez
JSON, Unicode'u ASCII'ye kaçırmak yerine korur, kontrol karakterlerini kaçırır ve bir tüketicinin kaliteyi değerlendirmesi için ihtiyaç duyduğu meta veriyi içerir: tespit modu, güven, sınırlar, span değerleri, başlık bayrakları ve devamlılık bilgisi. Çıkarılan tabloları sonraki bir sisteme besliyorsanız JSON'u tercih edin, çünkü bir CSV satırı size geldiği tablonun 0,51 güven puanı aldığını söyleyemez:
// Belge genelinde çıkarma, yalnızca güvenilmeye değer tabloları tutma
Tables := Pdf.ExtractDocumentTables(Options);
for I := 0 to High(Tables) do
begin
if Tables[I].Confidence < 0.75 then
begin
Log(Format('page %d table needs review (%.2f)',
[Tables[I].PageNumber, Tables[I].Confidence]));
Continue;
end;
if Tables[I].ContinuationGroup > 0 then
AppendToGroup(Tables[I].ContinuationGroup, Tables[I].ToJson)
else
EmitStandalone(Tables[I].ToJson);
end;
Ayarlama ve Ne Zaman Duracağını Bilmek
Üç ayar diğerlerinden daha önemlidir. MinConfidence kalite kapısıdır ve 0,5 kasıtlı olarak izin vericidir; otomatik alım için yükseltin, bir insanın her sonucu onayladığı bir inceleme arayüzü için düşürün. MinColumnGap, boşluk modunda neyin bir sütun sınırı sayıldığına karar verir ve yoğun raporlardaki sıkı ayarlı tablolar, 12 puntoluk varsayılandan düşürülmesini gerektirebilir. MaxRowGapFactor, dikey mesafenin bir tabloyu ne zaman sonlandırdığına karar verir; bu, ara sıra boş satırlara sahip tablolar için önemlidir
Sınırlar konusunda dürüst olun. Çizgili tablolar güvenilir şekilde çıkarılır. Temiz hizalanmış boşluk tabloları iyi çıkarılır. Döndürülmüş metne sahip tablolar, iç içe geçmiş tablolar veya içeriği başka bir satır gibi görünen bir şeye sarılan hücreler, parametreler nasıl ayarlanırsa ayarlansın incelemeye ihtiyaç duyacaktır. Bunlar için yapılandırılmış metin modeli, alana özgü bir okuyucu oluşturmak için ham malzemeyi verir; yapılandırılmış metin blokları ve okuma sırası başlığında anlatılmıştır
Yararlı bir eşleşme: taranmış bir belgenin hiç metni olmadığında tablo tespiti, bir metin katmanı var olana kadar üzerinde çalışacak hiçbir şeye sahip olmaz. Önce bir tane ekleyin, taranmış PDF'lere aranabilir bir metin katmanı ekleme başlığında anlatıldığı gibi, ardından çıkarın. Bir OCR sağlayıcısının döndürdüğü kelime kutuları, tam olarak boşluk tespitinin ihtiyaç duyduğu girdidir
Tablo çıkarma, yapılandırılmış metin ve yeniden akış, Delphi, C++Builder ve Lazarus'ta aynı sayfa modelinden okur; tam API, Delphi için PDFium Component sayfasında açıklanmıştır