1.2.1 キーワードの指定による検索

1-2-第1項キーワードの指定による検索

狙い・効果

与えられたキーワードで検索し、該当箇所の矩形を取得します。

処理の概要

ページ番号とキーワードを入力して検索し、ヒットしたキーワードのPDF上の矩形座標を表示します。ページ0を指定すると全ページを検索します。キーワードは複数指定できます。これはこの節の残りのプログラムでも同様です。また、ヒットしたキーワードに改行が混じっているなど、矩形が一つでない場合は複数の矩形座標が表示されます。

『PDF Tool API』の主な機能

PtlPDFDocument.APIsearchText(PtlParamSearchText param): 与えられたPDF全体に対してテキスト検索を実行する

PtlPage.APIsearchText(PtlParamSearchText param): 取得したページオブジェクトに対してテキスト検索を実行する

PtlParamSearchText: テキスト検索のパラメータを表現したクラス

PtlParamSearchText.APIappendText(java.lang.String text): 検索するテキストを追加する

PtlSearchTextResults: テキスト検索結果のコンテナを表現したクラス

PtlSearchTextResult: テキスト検索結果を表現したクラス

PtlSearchTextResultDetails: テキスト検索結果の詳細のコンテナを表現したクラス

PtlSearchTextResultDetail: テキスト検索結果の詳細を表現したクラス

PtlSearchTextResultDetail.APIgetQuadPoint(): テキスト検索した文字のQuadPointを取得する

PtlQuadPoint: PDFの矩形4隅座標を表現したクラス

プログラム例

package cookbook;

import jp.co.antenna.ptl.*;

public class SearchText {
    static final int NUM_OF_ARG_BEFORE_TEXT = 2;

    // そのクラスのusageを表示する関数
    private static void printUsage(){
        System.out.println("usage: java SearchText in-pdf-file" + 
                           " page-to-search searching-text... ");
        System.out.println("page-to-search:");
        System.out.println("0: 全ページから検索 0以外: 指定ページから検索");
    }
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        if (args.length < 3)
        {
            printUsage(); // usageメッセージの表示
            return;
        }

        // コマンドライン引数の読み取り・判定
        int pageToSearch = Integer.parseInt(args[1]); // ページ数
        // 検索テキストの設定
        int numOfSearchingText = args.length - NUM_OF_ARG_BEFORE_TEXT; 
        String[] arrayTextsToSearch = new String[numOfSearchingText];
        for (int i = 0; i < numOfSearchingText; i++){
            arrayTextsToSearch[i] = args[i + NUM_OF_ARG_BEFORE_TEXT];
        }

        try (PtlParamInput inputFile = new PtlParamInput(args[0]);
             PtlPDFDocument doc = new PtlPDFDocument())
        {
            // PDFファイルをロード
            doc.load(inputFile);

            // ページ番号が0を指定された場合はドキュメント全体から検索。
            if(pageToSearch == 0){
                searchTextInDocument(doc, arrayTextsToSearch);
            } else {
                // それ以外であれば指定ページ番号を検索。
                int wholePageNum = doc.getPageCount();
                //pageToSearchのエラー処理
                if(wholePageNum < pageToSearch)
                {
                    System.out.println("ERROR: page-to-searchはPDFの総ページ数より"+
                                       "小さい値を指定してください。");
                    System.out.println("総ページ数:" + wholePageNum);
                    printUsage();
                    return;
                }
                // 指定ページ番号内を検索。
                searchTextInPage(doc, arrayTextsToSearch, pageToSearch);
            }
        }

	...【ExtractText.javaと同じ処理のため省略
	 ・エラーメッセージ処理と出力】...

    }    
    /**
     * 
     * @param doc
     * @param arrayTextsToSearch 
     */
    private static void searchTextInDocument(PtlPDFDocument doc,
                                             String[] arrayTextsToSearch)
        throws PtlException {
        System.out.println("ドキュメント全体から検索します。");
        try(PtlParamSearchText paramSearchText = new PtlParamSearchText()) {
            // 検索パラメータに対象文字列を追加
            for(String textToSearch: arrayTextsToSearch) {
                paramSearchText.appendText(textToSearch);
            }
            // 検索結果コンテナクラスに検索結果を取得し、displaySearchResultsを呼び出す
            try(PtlSearchTextResults resultsContainer = doc.searchText(paramSearchText)) {
                displaySearchResults(resultsContainer);
            }
        }

    }

    private static void searchTextInPage(PtlPDFDocument doc,
                                         String[] arrayTextsToSearch,
                                         int pageToSearch)
        throws PtlException {
        System.out.println( pageToSearch +  "ページ目から検索します。");
        //ページコンテナの取得
        try (PtlPages pages = doc.getPages()) {
            // ページコンテナが空かどうか
            if (pages.isEmpty()) {
                System.out.println("ERROR : ページコンテナが空");
                return;
            }

            // ページの取得(index番号は0が先頭のため1を引く)
            try (PtlPage page = pages.get(pageToSearch - 1);
                 PtlParamSearchText paramSearchText = new PtlParamSearchText()) {
                // 検索パラメータに対象文字列を追加
                for(String textToSearch: arrayTextsToSearch) {
                    paramSearchText.appendText(textToSearch);
                }
                // 検索結果コンテナクラスに検索結果を取得
                try(PtlSearchTextResults resultsContainer =
                    page.searchText(paramSearchText)) {
                    displaySearchResults(resultsContainer);
                }
            }
        }
    }

    // 検索結果を表示する関数
    private static void displaySearchResults(PtlSearchTextResults resultsContainer)
        throws PtlException {
        // 検索件数の取得
        int resultCount = resultsContainer.getCount();
        System.out.println("検索結果 : " + resultCount + "件見つかりました。");

        // 各検索結果の出力
        for(int i = 0; i < resultCount; i++) {
            System.out.print("searchResult No." + (i + 1) + " : ");

            // index番号が i のテキスト検索結果・ページ番号を取得。
            // (index番号、ページ番号は0が先頭)
            try(PtlSearchTextResult searchResult = resultsContainer.get(i)) {
                System.out.println((searchResult.getPageNumber() + 1) + "ページ目");
                System.out.println("searchResult keyword : " + searchResult.getKeyword());
                // 検索結果の詳細コンテナを取得。
                try(PtlSearchTextResultDetails resultDetails =
                    searchResult.getResultDetails()) {

                    // resultDetailsの中身が1個だった場合(処理の軽量化のため場合分け)
                    if(resultDetails.getCount() == 1) {
                        printResultQuadPoints(resultDetails.get(0));
                    } else {
                        // 複数だった場合
                        for(int j = 0; j < resultDetails.getCount(); j++) {
                            System.out.println("searchResultDetail No. :" + (j + 1));
                            printResultQuadPoints(resultDetails.get(j));
                        }
                    }
                }
            }
        }
    }

// 該当テキスト検索結果の詳細コンテナ及びQuadPointを取得して表示する。
    private static void printResultQuadPoints(PtlSearchTextResultDetail resultDetail)
        throws PtlException {
        System.out.println("resultDetail keyword : " + resultDetail.getKeyword());
            // QuadPointの取得
        try(PtlQuadPoint quadPoint = resultDetail.getQuadPoint()) {

            // 各座標の表示
            System.out.println("該当箇所の矩形座標(x,y)はそれぞれ" +
                               "左下・右下・左上・右上の順に、");
            printXYCoordinate(quadPoint.getBottomLeft());
            printXYCoordinate(quadPoint.getBottomRight());
            printXYCoordinate(quadPoint.getTopLeft());
            printXYCoordinate(quadPoint.getTopRight());
            System.out.println("です。");
        }
    }

    private static void printXYCoordinate(PtlPoint point) throws PtlException {
        System.out.println("(" + point.getX() + "," + point.getY() + "), ");
    }
}

プログラムファイル名

SearchText.java

入出力操作の例

C:\samples>java cookbook.SearchText 
usage: java SearchText in-pdf-file page-to-search searching-text... 

C:\samples>java cookbook.SearchText novelText.pdf 2 アッタスン 
2ページ目から検索します。
検索結果 : 1件見つかりました。
searchResult No.1 : 2ページ目
searchResult keyword : アッタスン
searchResultDetail No. :1
resultDetail keyword : アッタスン
該当箇所の矩形座標(x,y)はそれぞれ左下・右下・左上・右上の順に、
(36.406532,231.26463), 
(54.94863,231.26463), 
(36.406532,234.97507), 
(54.94863,234.97507), 
です。
searchResultDetail No. :2
resultDetail keyword : アッタスン
該当箇所の矩形座標(x,y)はそれぞれ左下・右下・左上・右上の順に、
(67.26773,123.356964), 
(85.80947,123.356964), 
(67.26773,127.06739), 
(85.80947,127.06739), 
です。
-- 完了 --

novelText.pdfの2ページ目で「アッタスン」という文字列の位置を次の図の赤で示しました。

1.2.1 キーワードの指定による検索