使用粗体/斜体信息的PDFBox文本提取对某些文件不起作用

时间:2014-01-18 18:13:55

标签: java text pdfbox extraction

这个程序适用于我创建的PDF文件,但我必须获得Stedman的Dictionary.pdf的粗体和斜体信息,这似乎有一个隐藏此信息的技巧。任何建议都将受到热烈欢迎。

注意:      这是一个纯粹的自愿努力,以帮助一些医生朋友。

    package arspdfbox;

    import java.io.*;
    import org.apache.pdfbox.exceptions.InvalidPasswordException;

    import org.apache.pdfbox.pdmodel.PDDocument;
    import org.apache.pdfbox.pdmodel.PDPage;
    import org.apache.pdfbox.pdmodel.common.PDStream;
    import org.apache.pdfbox.util.PDFTextStripper;
    import org.apache.pdfbox.util.TextPosition;
    import java.io.IOException;
    import java.util.List;

    public class PrintTextLocations extends PDFTextStripper {

        public PrintTextLocations() throws IOException {
            super.setSortByPosition(true);
        }

        public static void main(String[] args) throws Exception {

            PDDocument document = null;
            try {
                File input = new File("Stedman_Medical_Dictionary.pdf");
                //File input = new File("results/FontExample5.pdf");
                document = PDDocument.load(input);
                if (document.isEncrypted()) {
                    try {
                        document.decrypt("");
                    } catch (InvalidPasswordException e) {
                        System.err.println("Error: Document is encrypted with a password.");
                        System.exit(1);
                    }
                }
                PrintTextLocations printer = new PrintTextLocations();
                List allPages = document.getDocumentCatalog().getAllPages();
                //for (int i = 0; i < allPages.size(); i++) {
                for (int i = 99; i < 100; i++) {
                    PDPage page = (PDPage) allPages.get(i);
                    System.out.println("Processing page: " + i);
                    PDStream contents = page.getContents();
                    if (contents != null) {
                        printer.processStream(page, page.findResources(), page.getContents().getStream());
                    }
                }
            } finally {
                if (document != null) {
                    document.close();
                }
            }
        }

        /**
         * @param text The text to be processed
         */
        @Override /* this is questionable, not sure if needed... */
        protected void processTextPosition(TextPosition text)  {
            System.out.println("String[" + text.getXDirAdj() + ","
                    + text.getYDirAdj() + " fs=" + text.getFontSize() + " xscale="
                    + text.getXScale() + " height=" + text.getHeightDir() + " space="
                    + text.getWidthOfSpace() + " width="
                    + text.getWidthDirAdj() + "]" + text.getCharacter());
            System.out.append(text.getCharacter()+" <--------------------------------");
           // System.out.println("String[" + text.getXDirAdj() + "," + text.getYDirAdj() + " fs=" + text.getFontSize() + " xscale=" + text.getXScale() + " height=" + text.getHeightDir() + " space=" + text.getWidthOfSpace() + " width=" + text.getWidthDirAdj() + "]" + text.getCharacter());
            System.out.println(text.getFont().getBaseFont()); System.out.println(" Italic="+text.getFont().getFontDescriptor().isItalic()); 
            System.out.println(" Bold="+text.getFont().getFontDescriptor().getFontWeight()); 
            System.out.println(" ItalicAngle="+text.getFont().getFontDescriptor().getItalicAngle()); 
            //try{
            System.out.println(" xxxx="+text.getFont().getFontDescriptor().isFixedPitch());
            //} catch (IOException ioex){}

        }

    }

2 个答案:

答案 0 :(得分:2)

  

这个程序适用于我创建的PDF文件,但我必须获得Stedman's Dictionary.pdf的粗体和斜体信息,这似乎有一个隐藏此信息的技巧。

您的程序也适用于Stedman的词典:PDF中这些词典样式页面上的文本信息使用相同的字体,包括普通,粗体,斜体等文本。样式仅出现在叠加图像中,这仅仅是图像而不是文本提取的信息来源。

详细说明:

看例如进入第132个文档页面的内容流(编号为110,随机选择)显示以下条目

entry for Bal'four's disease

以下来源:

/F1 22 Tf
BT
1 0 0 1 61 2559 Tm
(Bal'four's)Tj
ET
/F1 21.46 Tf
BT
1 0 0 1 210 2559 Tm
(disease')Tj
ET
/F1 24.76 Tf
BT
1 0 0 1 327 2561 Tm
([George)Tj
ET
/F1 22.71 Tf
BT
1 0 0 1 444 2563 Tm
(Williatn)Tj
ET
/F1 23.33 Tf
BT
1 0 0 1 565 2564 Tm
(Balfour,)Tj
ET
/F1 24.76 Tf
BT
1 0 0 1 692 2566 Tm
(English)Tj
ET
/F1 23 Tf
BT
1 0 0 1 94 2525 Tm
(physician,)Tj
ET
/F1 24.09 Tf
BT
1 0 0 1 252 2526 Tm
(1822-1903.])Tj
ET
/F1 25.93 Tf
BT
1 0 0 1 447 2530 Tm
(Chloroma.)Tj
ET

即。相同的字体( F1 )用于每个单词,没有不同的样式,只是大小不同:

  • “Bal'four's”22岁
  • “疾病”在21.46
  • “[George”at 24.76
  • “Williatn”at 22.71
  • “Balfour,”23.33
  • “English”at 24.76
  • “医生”,23岁
  • “1822-1903。”“at 24.09
  • “部绿色”。在25.93

(坐标在手边的页面上缩放了0.23945倍;因此,PDFBox将为您提供按该因子缩放的数字,而不是列出的尺寸。)

您看到粗体( Bal'four's disease')或斜体( Balfour,)文字的原因是此文字信息是在渲染模式3中“渲染”,即不可见,并在其上显示扫描图像。因此,您没有任何可靠的信息(缺少对该图像应用样式文本的OCR)。

据说,这些尺寸,如果试图看到任何相关性,对于粗体文本似乎较小,分界线介于22和22.5之间(我看过三四个字典条目的印象。因此,您可能会尝试从小尺寸中获得粗体。我不会指望这是一个肯定的事情,但是,一些粗体文字可能更大,一些非粗体更小

答案 1 :(得分:1)

Try this :

protected void processTextPosition(TextPosition text)  {
    boolean isBold,isItalic;
    String s = null ;

    if (text.getFont().getFontDescriptor() != null )
    {   
                    {
            if (text.getFont().getFontDescriptor().isForceBold() ||  
            text.getFont().getFontDescriptor().getFontWeight() > 680 )
            {
            isBold = true;
           // System.err.println(text.getCharacter()+"==1");
            if (text.toString() == null || text.toString().isEmpty() ||
            text.toString().trim().isEmpty()){
            //  System.err.println(text.getCharacter()+"2");
                s = new StringBuilder().append("").append(text).toString();
                out.print(s);
            }
            s = new StringBuilder().append("").append(text).toString();
            out.print(s);
        }
      }
}

if (text.getFont().getFontDescriptor().isItalic())
        {
            isItalic = true;
        }

    if (text.toString() == null || text.toString().isEmpty() ||
    text.toString().trim().isEmpty()){
        s = new StringBuilder().append("").append(text).toString();
        out.print(s);
    }

}