9

iTextを使用してPDFファイルからテキストを抽出する必要があります。

問題は次のとおりです。一部のPDFファイルには2つの列が含まれており、テキストを抽出すると、結果として列がマージされたテキストファイルが表示されます(つまり、同じ行の両方の列からのテキスト)

これはコードです:

public class pdf
{
    private static String INPUTFILE = "http://www.revuemedecinetropicale.com/TAP_519-522_-_AO_07151GT_Rasoamananjara__ao.pdf" ;
    private static String OUTPUTFILE = "c:/new3.pdf";

    public static void main(String[] args) throws DocumentException, IOException {
        Document document = new Document();
        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(OUTPUTFILE));
        document.open();

        PdfReader reader = new PdfReader(INPUTFILE);
        int n = reader.getNumberOfPages();

        PdfImportedPage page;

        // Go through all pages
        for (int i = 1; i <= n; i++) {
            page = writer.getImportedPage(reader, i);
            Image instance = Image.getInstance(page);
            document.add(instance);
        }

        document.close();

        PdfReader readerN = new PdfReader(OUTPUTFILE);
        for (int i = 1; i <= n; i++) {
            String myLine = PdfTextExtractor.getTextFromPage(readerN,i);
            System.out.println(myLine);

            try {             
                FileWriter fw = new FileWriter("c:/yo.txt",true);
                fw.write(myLine);
                fw.close();
            }catch (IOException ioe) {ioe.printStackTrace(); }
    }
}

仕事を手伝ってくれませんか。

4

6 に答える 6

29

私はiTextテキスト抽出サブシステムの作成者です。あなたがする必要があるのはあなた自身のテキスト抽出戦略を開発することです(あなたがどのようPdfTextExtractor.getTextFromPageに実行されるかを見れば、あなたはプラグ可能な戦略を提供できることがわかるでしょう)。

列の開始位置と停止位置をどのように決定するかは完全にあなた次第です-これは難しい問題です-PDFには列の概念がありません(つまり、単語の概念すらありません-単にまとめるだけですデフォルトの戦略が提供するテキスト抽出は非常に注意が必要です)。列がどこにあるかを高度に知っている場合は、テキストレンダリングリスナーコールバックで領域フィルターを使用できます(これを行うためのコードがiTextライブラリにあり、最新バージョンのiText In Actionブックに詳細な例が示されています) 。

任意のデータから列を取得する必要がある場合は、事前にアルゴリズムを実行する必要があります(何かが機能する場合は、確認したいと思います)。これにアプローチする方法に関するいくつかのアイデア:

  1. デフォルトのテキスト抽出戦略(LocationAware ...)で使用されているものと同様のアルゴリズムを使用して、単語とX / Y位置のリストを取得します(回転角も考慮に入れてください)。
  2. 単語ごとに、ページの高さ全体を走る架空の線を描きます。同じX位置で始まる他のすべての単語をスキャンします。
  3. スキャン中に、X位置と交差する単語も探します(ただし、X位置から開始しないでください)。これにより、ページ上の列の開始/停止Y位置の潜在的な場所がわかります。
  4. 列XとYができたら、領域フィルター処理されたアプローチに頼ることができます

同様に実行可能な別のアプローチは、描画操作を分析し、長い水平線と垂直線を探すことです(列がテーブルのような形式で区切られていると仮定します)。現在、iTextコンテンツパーサーにはこれらの操作のコールバックがありませんが、大きな問題なく追加することは可能です。

于 2010-10-27T07:04:25.313 に答える
1

ファイルが構造化コンテンツを使用しない限り、テーブルはPDFの構造として存在しません。PDFファイルとは何かわかりますか?テキスト抽出の問題を説明するブログ記事をhttp://www.jpedal.org/PDFblog/?p=228に書きました。

于 2010-10-27T07:27:19.833 に答える
1

PdfBoxを試すこともできますが、それはすべてPDFの構造の欠如に戻ります。これは、主に表示用の最終ファイル出力形式です。

于 2010-10-27T07:28:31.313 に答える
1

PDFTextStreamがその1つです!少なくとも、列の値を特定することはできます。以前、私はiTextを使用していて、戦略の定義に行き詰まりました。それは難しい。

このAPIは、より多くのスペースを配置することで列セルを分離します。その修正。あなたは論理を置くことができます。(これはiTextにはありませんでした)。

import com.snowtide.PDF;
import com.snowtide.pdf.Document;
import com.snowtide.pdf.OutputTarget;

public class PDFText {
    public static void main(String[] args) throws java.io.IOException {
        String pdfFilePath = "xyz.pdf";

        Document pdf = PDF.open(pdfFilePath);
        StringBuilder text = new StringBuilder(1024);
        pdf.pipe(new OutputTarget(text));
        pdf.close();
        System.out.println(text);
   }
}

stackoverflowでこれに関連する質問がありました!

于 2016-10-06T16:39:21.637 に答える
0

抽出するファイルは、データ抽出の目的ではかなり複雑です。テーブル、画像、複数の列があります。読み取り順序を決定し、テーブルデータを処理するには、特別なアルゴリズムが必要になります。

ここで何を達成しようとしていますか?代わりに市販のOCRエンジンを使用して、すべてのハードワークを実行し、そこからデータを処理することができます。

于 2010-10-27T05:30:31.443 に答える
0

私の答えは少し遅れていることを私は知っています。しかし、私は次のコードを使用してPDFファイルから特定のページを読み取ります。列の読み取りに問題はなく、マージされたテキストもありませんでした。各列は他の列とは別に印刷されています。

    /**
 * Get plain text from a specific page in a pdf file.
 * @param pdfPath
 * @return
 * @throws IOException
 */
public static String getPageContent(String pdfPath, int pageNumber) throws IOException
{
    PdfReader reader = new PdfReader(pdfPath); 

    StringWriter output = new StringWriter();  

        try {
            output.append(PdfTextExtractor.getTextFromPage(reader, pageNumber, new SimpleTextExtractionStrategy()));

        } catch (OutOfMemoryError e) {

            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    return output.toString();
}

ページの一部、たとえば1列のみを抽出することを検討している場合は、列のサイズを取得する必要があります。まだ少し注意が必要ですが、列の最初のテキストをすでに知っている場合は、これを理解できる可能性があります(幅と高さを推定する方法で)。これは、長方形の領域を使用して実行できます。以下のコードを参照してください。ポイント測定を間違えた場合は申し訳ありません。以下のコードでは、ページ全体のサイズを取得しようとしています。

public static String getPageContent(String pdfPath, int pageNumber) throws IOException
{

    PDDocument pdDoc = PDDocument.load(pdfPath);
    PDPage specPage = (PDPage)pdDoc.getDocumentCatalog().getAllPages().get( 0 );

PDFTextStripperByArea stripper = new PDFTextStripperByArea();
stripper.setSortByPosition( true );
float width = (specPage.getMediaBox().getHeight())*25.4f;
float height = (specPage.getMediaBox().getWidth())*25.4f;
Rectangle rect = new Rectangle( 0, 0, Math.round(width), Math.round(height));
stripper.addRegion( "class1", rect );
List allPages = pdDoc.getDocumentCatalog().getAllPages();
PDPage firstPage = (PDPage)allPages.get( pageNumber-1 );
stripper.extractRegions( firstPage );

return stripper.getTextForRegion( "class1" );

}

于 2014-02-13T17:19:10.330 に答える