この記事は公開から3年以上経過しています。
VSCodeを使ったC#(.NET 5)開発で、PDFファイル内にある表からデータを抽出する方法。
機械学習などで公的機関のPDF形式オープンデータを取り込みたい場合などに、役に立つかもしれません。
サンプルソースコード(C#)
本サンプルでは以下の素晴らしいNuGetライブラリを利用しています。
PDFScrapingTest210916.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
<!-- PDFを出力ディレクトリにコピー -->
<ItemGroup>
<None Update="pdf_table_test.pdf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</None>
</ItemGroup>
<!-- NuGetパッケージ -->
<ItemGroup>
<PackageReference Include="PdfPig" Version="0.1.5-alpha001" />
<PackageReference Include="Tabula" Version="0.1.1" />
</ItemGroup>
</Project>
Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using Tabula;
using Tabula.Extractors;
using UglyToad.PdfPig;
namespace PDFScrapingTest210916
{
class Program
{
private static readonly IExtractionAlgorithm ea = new SpreadsheetExtractionAlgorithm();
static void Main(string[] args)
{
// PDFを開く
using var pdfDoc = PdfDocument.Open("pdf_table_test.pdf", new ParsingOptions() { ClipPaths = true });
// データを抽出するPDFページ番号を指定
var oe = new ObjectExtractor(pdfDoc);
var targetPageNumbers = Enumerable.Range(1, 1);
var pages = oe.Extract(targetPageNumbers);
// PDF表をCSV形式で表示
foreach (var row in GetRows(pages))
{
Console.WriteLine(string.Join(",", row.Select(r => r.GetText())));
}
Console.ReadKey();
}
// PDF上の全表を行データとして抽出
private static IEnumerable<IReadOnlyList<Cell>> GetRows(PageIterator pages)
{
while (pages.MoveNext())
{
foreach (var table in ea.Extract(pages.Current))
{
foreach (var row in table.Rows)
{
yield return row;
}
}
}
yield break;
}
}
}
テスト用PDFファイル
実行結果
上図のとおり、PDF表からCSV形式にデータを抽出できていることが分かります。
但し、公的機関のオープンデータのような複雑な表のデータの場合には思い通りに抽出できない場合のほうが多いため、実運用では抽出後のデータを目視で確認したうえで必要に応じて手作業による修正が必要になると思います。
どうしても「全自動で抽出したい!」…という場合、入力データの形が決まっていればTabulaのBasicExtractionAlgorithm
を使って自力で座標を解析することで目標が達成できるかもしれません。
興味のある方は是非試してみてください。
参考ウェブサイトなど
以上です。