在C#中从PDF中提取格式信息

时间:2016-11-18 00:34:14

标签: c# .net

我需要制定一个程序,可以分析和理解某些具有特定结构和格式的PDF中内容的上下文和语义关系。

下面是一个示例,其中显示了此类PDF的一部分内容: enter image description here

所以我需要一个PDF阅读库,它不仅可以提取文本,还可以提取PDF中的metedata,如字体大小,字体样式(粗体,itali),背景颜色,表格及其子元素,表格单元格背景颜色,复选框,元素位置等。

是否有任何免费的.NET库可以完成这项工作?非常感谢。

PS:我知道这篇文章:Extract Data from .PDF files,但图书馆的能力没有详细说明。

2 个答案:

答案 0 :(得分:2)

我没有快速回答,但过去两周我一直在解决这个确切的问题,并取得了成功。我使用Apache PDFBox,它将PDF文本提取到TextPositions。这些TextPosition包含有关文本中每个字符的信息(位置,粗体,斜体,字体等)。我使用这些信息来设置所有表格元素的边界框和诸如文本对齐,列成员资格等的倒带,然后在Excel中重新创建PDF页面及其表格,不到1000行代码。

我不必提取像复选框这样的图形元素,但Apache PDFBox确实提取到COSStreams,图形和表单元素很可能会从这些流中解析 - 我还没有。我的代码将能够重建您显示的表,并且只会缺少复选框和背景颜色。

我已经找到了一个比我更简单的解决方案而且做得很短,似乎没有简单的方法可以做到这一点。

编辑:如果这还没有劝阻你,我可以告诉你如何开始。首先,扩展PDFTextStripper或PDFTextStripperByArea。这使您可以通过processTextPosition覆盖访问TextPositions - 以下代码显示了我如何将TextPositions转换为我自己的自定义类TextChar。然后,我使用相对文本位置来计算基本的上下文信息:

public class PDFStripper : PDFTextStripper
    {
        private List<TextChar>[] tcPages;

        public PDFStripper(java.util.List pages)
        {
            int pagecount = pages.size();
            tcPages = new List<TextChar>[pagecount+1];
            base.processPages(pages);
        }

        protected override void processTextPosition(TextPosition tp)
        {
            PDGraphicsState gs = getGraphicsState();
            TextChar tc = BuildTextChar(tp, gs);
            int currentPageNo = getCurrentPageNo();
            if (tcPages.ElementAtOrDefault(currentPageNo) == null)
            {
                tcPages[currentPageNo] = new List<TextChar>();
            }
            tcPages[currentPageNo].Add(tc);
        }

        private static TextChar BuildTextChar(TextPosition tp, PDGraphicsState gstate)
        {
            TextChar tc = new TextChar();
            tc.Char = tp.getCharacter()[0];

            float h = (float)Math.Floor(tp.getHeightDir());
            tc.Box = new RectangleF
            (
                tp.getXDirAdj(),
                (float)Math.Round(tp.getYDirAdj(), 0, MidpointRounding.ToEven) - h, // adjusted Y to top
                tp.getWidthDirAdj(),
                h
            );

            tc.Direction = tp.getDir();
            tc.SpaceWidth = tp.getWidthOfSpace();

            tc.Font = tp.getFont().getBaseFont();
            tc.FontSize = tp.getFontSizeInPt();

            try
            {
                int[] flags =     
                     GetBits(tp.getFont().getFontDescriptor().getFlags());
                tc.IsBold = findBold(tp, flags, gstate);
                tc.IsItalic = findItalics(tp, flags);
            }
            catch { }

            return tc;
        }

        protected override void writePage() { return; } //prevents exception
    }

答案 1 :(得分:1)

添加此NuGet包https://www.nuget.org/packages/TikaOnDotNet/。 它是apache tika的dotnet版本

然后这样做:

var extracted = new TikaOnDotNet.TextExtractor().Extract("file.pdf");
var text = extracted.Text;
var metaData = extracted.Metadata;

祝你好运好友:)