使用pdfboxnet提取pdf文本位置

时间:2016-10-28 01:36:31

标签: c# pdf pdfbox

我需要使用c#

提取带有坐标的文本

我正在使用pdfboxnet使用c# 这是

class Items:

这是程序的输出

http://pastebin.com/JwA2YaC7

我将输出链接到pastebin,因为它很长。

这是我使用的pdf。

https://drive.google.com/open?id=0B45rDxvaXzsmcFo1QXhNdDBXT28

我在这里有两个问题。我怎么知道这些人物是一个字?

使用x,y?这是对的吗?

另一个问题是。为什么它不提取所有文本?或者我错过了一些代码?我知道这个等式不能被提取出来,但是当我提取pdf文本时,pdfbox有多准确?

我已经尝试过bytescout,但我没有许可证,所以即时通讯尝试pdfbox。但bytescout可以提取单词及其坐标

1 个答案:

答案 0 :(得分:2)

PDF和文字

可移植文档格式(PDF)不知道单词的概念,或者至少它不要求将文本内容清楚地排列为单词。

(有一个特征,单词间距,只有在使用明确标识的空格字形来分隔构成单个单词的字形组时才有效,但此功能通常不会使用。)

因此,要识别PDF中的单词,确实必须分析它们中的字形及其位置。

PDFBox和文字

PDFTextStripper基础解析内容并分别报告通过processTextPosition方法呈现的每个字形。然后,该方法的默认实现通过在同一位置对字形进行一些处理来收集这些单独的字形数据。

当解析所有页面时,收集的数据被排列成行(在排序后SortByPositiontrue),然后根据一些启发法将其分成单词,而这些启发式反过来又是转发到writeString,将该单词写入缓冲区,其内容最终以提取的文本形式返回。

(这有点简化,但应该足以解决手头的问题。)

因此,这两个提到的方法是用自己的代码覆盖的主要代码位置。

  • 如果有一个,则覆盖processTextPosition
    • 希望字形字符在流中的原始顺序中而不是排序和排列,或者如果一个
    • 需要在呈现字形时访问并响应已解析流的状态。
  • 另一方面,如果对排序和排列的字形字符感兴趣,则会覆盖writeString

对于某些任务,实际上需要覆盖两者,例如就像在this answer中一样。

PDFBox&的示例爪哇

PDFBox& amp;中的一个简单实现Java(在评论中OP提到这也可以帮助他)可能看起来像这样

String extractWordLocations(PDDocument document) throws IOException
{
    PDFTextStripper stripper = new PDFTextStripper()
    {
        @Override
        protected void writeString(String text, List<TextPosition> textPositions) throws IOException
        {
            super.writeString(text, textPositions);

            TextPosition firstProsition = textPositions.get(0);
            TextPosition lastPosition = textPositions.get(textPositions.size() - 1);
            writeString(String.format("[%s - %s / %s]", firstProsition.getXDirAdj(), lastPosition.getXDirAdj() + lastPosition.getWidthDirAdj(), firstProsition.getYDirAdj()));
        }
    };
    stripper.setSortByPosition(true);
    return stripper.getText(document);
}

(来自ExtractText.java

将此类应用于您的示例文件

try (   InputStream documentStream = getClass().getResourceAsStream("mathml88.pdf" );
        PDDocument document = PDDocument.load(documentStream))
{
    String wordLocations = extractWordLocations(document);

    System.out.println("\n'mathml88.pdf', extract with word locations:");
    System.out.println(wordLocations);
    System.out.println("***********************************");
}

ExtractText测试方法testExtractWordLocationsFromMathml88

结果

88[74.34 - 85.2491 / 61.241028] Chapter[378.835 - 413.37317 / 61.241028] 3.[416.10043 - 424.28226 / 61.241028] Presentation[429.73682 - 483.67136 / 61.241028] Markup[486.39862 - 520.93677 / 61.241028]
3.4.3.3[74.34 - 104.34002 / 97.10602] Examples[120.70367 - 163.72914 / 97.10602]
The[74.34 - 91.30365 / 117.565] msubsup[93.55299 - 133.57849 / 117.565] is[135.816 - 143.09236 / 117.565] most[145.33963 - 166.55782 / 117.565] commonly[168.80508 - 215.47418 / 117.565] used[217.72145 - 237.71782 / 117.565] for[239.976 - 252.69601 / 117.565] adding[254.94328 - 284.63788 / 117.565] sub/superscript[286.88516 - 352.93976 / 117.565] pairs[355.18704 - 376.39432 / 117.565] to[378.6416 - 387.12888 / 117.565] identifiers[389.37616 - 433.0125 / 117.565] as[435.2598 - 444.34708 / 117.565] illustrated[446.60526 - 490.23068 / 117.565] above.[492.48886 - 520.9398 / 117.565]
However,[74.34 - 115.90368 / 131.11401] another[118.88187 - 151.59825 / 131.11401] important[154.56552 - 196.991 / 131.11401] use[199.96918 - 214.511 / 131.11401] is[217.48918 - 224.76555 / 131.11401] placing[227.73282 - 259.8492 / 131.11401] limits[262.8274 - 287.68918 / 131.11401] on[290.66736 - 301.57648 / 131.11401] certain[304.54376 - 334.22736 / 131.11401] large[337.20554 - 358.81644 / 131.11401] operators[361.78372 - 402.37646 / 131.11401] whose[405.35464 - 433.22742 / 131.11401] limits[436.2056 - 461.06738 / 131.11401] are[464.03467 - 477.35464 / 131.11401] tradition-[480.33282 - 520.93646 / 131.11401]
ally[74.34 - 90.70365 / 144.664] displayed[93.812744 - 135.62732 / 144.664] in[138.74731 - 147.23459 / 144.664] the[150.34369 - 163.6746 / 144.664] script[166.7837 - 191.02373 / 144.664] positions[194.14372 - 233.54736 / 144.664] even[236.65646 - 256.8165 / 144.664] when[259.9256 - 283.55472 / 144.664] rendered[286.6747 - 324.82382 / 144.664] in[327.94382 - 336.4311 / 144.664] display[339.5402 - 371.05658 / 144.664] style.[374.16568 - 397.5002 / 144.664] The[400.6202 - 417.58386 / 144.664] most[420.69296 - 441.91116 / 144.664] common[445.02026 - 483.20212 / 144.664] of[486.3221 - 495.4094 / 144.664] these[498.5185 - 520.93665 / 144.664]
is[74.34 - 81.61636 / 158.21301] the[84.343636 - 97.67456 / 158.21301] integral.[100.40183 - 136.29279 / 158.21301] For[139.02007 - 154.00917 / 158.21301] example,[156.73645 - 196.26012 / 158.21301]
?[120.703995 - 126.847725 / 193.42804] 1[131.73799 - 136.22119 / 196.88904]
ex[138.04799 - 147.33707 / 208.36603] dx[149.18999 - 160.47609 / 208.36603]
0[126.83699 - 131.32019 / 217.77405]

当你看到一个表达式&#34; [x start - x end / y]&#34;附在每个单词上。

将所有信息放入String仅用于概念验证目的。对于生产用途,您可能希望创建一个WordWithPosition类,为writeString中的每个单词创建该类的实例,并将这些对象存储在最终检索到的内容的List中来自PDFTextStripper扩展程序。