# 루씬 문서 인덱싱(txt, htm, html, xml, pdf, doc, docx, xls, xlsx, ppt, pptx)


사용 버전
Lucene Library : 4.3.0
한글 형태소 분석 Library : koreananalyzer.4x

파서 클래스 : PdfFileParser, DocFileParser, DocxFileParser
http://develop.sunshiny.co.kr/913


import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.kr.KoreanAnalyzer;
// import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.FieldType;
import org.apache.lucene.document.StringField;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.FieldInfo.IndexOptions;
import org.apache.lucene.index.IndexWriterConfig.OpenMode;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;

/**
 * @author Mubin Shrestha
 */
public class IndexerDoc {

    private final String sourceFilePath = "/data/docs";    // 문서 디렉토리
    private final String indexFilePath = "/data/indexs_doc";   // 색인 파일 저장 위치
    private final boolean isNew = true;  // 신규 생성여부
    
    private IndexWriter writer = null;
    private File indexDirectory = null;
    private String fileContent;  //temporary storer of all the text parsed from doc and pdf 

    private IndexerDoc() throws FileNotFoundException, CorruptIndexException, IOException {
        try {
            long start = System.currentTimeMillis();
            createIndexWriter(); // 인덱스 객체 오픈
            checkFileValidity(new File(sourceFilePath)); // 문서 파싱및 인덱스에 적재
            closeIndexWriter(); // 인덱스 객체 닫음
            long end = System.currentTimeMillis();
            System.out.println("Total Document Indexed : " + TotalDocumentsIndexed());
            System.out.println("Total time" + (end - start) / (100 * 60));
        } catch (Exception e) {
            System.out.println("Sorry task cannot be completed");
        }
    }

    private void createIndexWriter() {
        try {
            indexDirectory = new File(indexFilePath);
            if (!indexDirectory.exists()) {
                indexDirectory.mkdir();
            }
            FSDirectory dir = FSDirectory.open(indexDirectory);
            
            // 한글 형태소 분석기 사용
            Analyzer analyzer = new KoreanAnalyzer(Version.LUCENE_43);
            IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_43, analyzer);
            
            if (isNew) {
                // 신규 인덱스 생성(기존 생성된 인덱스 삭제)
                config.setOpenMode(OpenMode.CREATE);
            } else {
                // 기존 생성된 인덱스에 추가
                config.setOpenMode(OpenMode.CREATE_OR_APPEND);
            }
            
            writer = new IndexWriter(dir, config);
            
            
        } catch (Exception ex) {
            System.out.println("Sorry cannot get the index writer");
        }
    }

    /**
     * This function checks whenther the file passed is valid or not
     */
    private void checkFileValidity(File file) {
        File[] files = file.listFiles();

        for (int i=0; i<files.length; i++) {
          try {
              /**
               * # 하위의 디렉토리에 모든 파일을 조회하여 파싱작업
               */
              if(files[i].isDirectory()){ // ### 디렉토리일 경우 해당 디렉토리를 탐색 ###
                  checkFileValidity(files[i]); // 재귀 호출
              }else if(!files[i].isHidden()
                        && files[i].exists() 
                        && files[i].canRead() 
                        && files[i].length() > 0.0 
                        && files[i].isFile()) { // ### 파일인 경우 문서 파싱작업 ###
                  if(files[i].getName().endsWith(".txt") || files[i].getName().endsWith(".htm") || 
                     files[i].getName().endsWith(".html") || files[i].getName().endsWith(".xml")){
                      indexTextFiles(files[i]); // txt, htm, html, xml 파일의 텍스트 추출
                  System.out.println("Indexed Txt : " + files[i].getAbsolutePath() + " :-) ");
                  }else if(files[i].getName().endsWith(".doc") || files[i].getName().endsWith(".ppt") || files[i].getName().endsWith(".xls") ||
                          files[i].getName().endsWith(".docx") || files[i].getName().endsWith(".pptx") || files[i].getName().endsWith(".xlsx") ||
                          files[i].getName().endsWith(".pdf")
                          ){
                     StartIndex(files[i]); // document 파일들의 텍스트 추출
                  }
              }
          } catch (Exception e) {
              System.out.println("Sorry cannot index " + files[i].getAbsolutePath());
          }
      }
    }
    
    // pdf, doc, docx, xls, xlsx, ppt, pptx 파일의 내용을 파싱및 추출
    private void StartIndex(File file) throws FileNotFoundException, CorruptIndexException, IOException {
         fileContent = null;
        try {
            Document doc = new Document();
            if (file.getName().endsWith(".pdf")) {
                //call the pdf file parser and get the content of pdf file in txt format
                fileContent = new PdfFileParser().PdfFileParser(file.getAbsolutePath());
            }
            
            // 확장자 doc, ppt, xls 에 대한 텍스트 추출 처리
            if (file.getName().endsWith(".doc") || file.getName().endsWith(".ppt") || file.getName().endsWith(".xls")) {
                //call the doc file parser and get the content of doc file in txt format
                fileContent = new DocFileParser().DocFileContentParser(file.getAbsolutePath());
            }
            
            // 확장자 docx, pptx, xlsx 에 대한 텍스트 추출 처리
            if (file.getName().endsWith(".docx") || file.getName().endsWith(".pptx") || file.getName().endsWith(".xlsx")) {
                fileContent = new DocxFileParser().docxFileContentParser(file.getAbsolutePath());
            }            
            
            // 필드 타입 설정
            FieldType fieldType = new FieldType(); 
            fieldType.setIndexed(true);    // 인덱스 포함 여부
            fieldType.setStored(true);      // 검색에 출력 여부
            fieldType.setTokenized(true);  // 필드 토큰화 여부
            fieldType.setIndexOptions(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS);
            /**
            ### FieldType - IndexOptions ###
            DOCS_AND_FREQS : 문서와 용어 빈도를 포함, 위치 생략 
            DOCS_AND_FREQS_AND_POSITIONS : 문서와 용어 빈도, 위치값을 포함 
            DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS : 문서와 용어 빈도, 위치값, 오프셋 포함 (# PDF 인덱싱 오류 발생)
            DOCS_ONLY : 문서만 색인, 용어 빈도, 위치 생략
             */
            doc.add(new StringField("fileName", file.getName(), Field.Store.YES));
            doc.add(new StringField("fullPath", file.getAbsolutePath(), Field.Store.YES));  
            doc.add(new Field("contents", fileContent, fieldType)); // 내용
            
            if (doc != null) {
                writer.addDocument(doc);
            }
            System.out.println("Indexed Doc : " + file.getAbsolutePath());
        } catch (Exception e) {
            System.out.println("error in indexing" + (file.getAbsolutePath()));
        }
    }

    // txt, htm, html, xml 파일의 내용을 파싱및 추출
    private void indexTextFiles(File file) throws CorruptIndexException, IOException {
        Document doc = new Document();
        fileContent = null;
        // 텍스트 파일을 EUC-KR 인코딩으로 가져오기
        BufferedReader buff = new BufferedReader(new InputStreamReader(new FileInputStream(file), "EUC-KR"));
        
        while(true)
        {
                String s = buff.readLine();
                if(s == null) break;
                fileContent += s;
//                System.out.println("s = " + s);
        }
        buff.close();
        
        // txt파일 이외의 문서(htm,html,xml)는 모든 태그형식(<로 시작, >로 끝나는)을 제거
        if(!file.getName().endsWith(".txt")){ 
            fileContent = removeTag(fileContent);
        }

        FieldType fieldType = new FieldType(); 
        fieldType.setIndexed(true);    // 인덱스 포함 여부
        fieldType.setStored(true);      // 검색에 출력 여부
        fieldType.setTokenized(true);  // 필드 토큰화 여부
//        fieldType.setStoreTermVectors(true);
        fieldType.setIndexOptions(IndexOptions.DOCS_ONLY);
        /**
        ### FieldType - IndexOptions ###
        DOCS_AND_FREQS : 문서와 용어 빈도를 포함, 위치 생략 
        DOCS_AND_FREQS_AND_POSITIONS : 문서와 용어 빈도, 위치값을 포함 
        DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS : 문서와 용어 빈도, 위치값, 오프셋 포함 
        DOCS_ONLY : 문서만 색인, 용어 빈도, 위치 생략
         */
        doc.add(new StringField("fileName", file.getName(), Field.Store.YES));
        doc.add(new StringField("fullPath", file.getAbsolutePath(), Field.Store.YES));  
        doc.add(new Field("contents", fileContent, fieldType)); // 내용
        
        if (doc != null) {
            writer.addDocument(doc);
        }
    }

    /**
     * This method returns the total number of documents indexed.
     * @return total number of documents indexed.
     */
    private int TotalDocumentsIndexed() {
        try {
            IndexReader reader = IndexReader.open(FSDirectory.open(indexDirectory));
            return reader.maxDoc();
        } catch (Exception ex) {
            System.out.println("Sorry no index found");
        }
        return 0;
    }

    /**
     *  closes the IndexWriter
     */
    private void closeIndexWriter() {
        try {
//            writer.optimize();
            writer.close();
        } catch (Exception e) {
            System.out.println("Indexer Cannot be closed");
        }
    }

    /**
     * 태그를 지움    
     */
    private static String removeTag(String s) {
        return s.replaceAll("<[^>]*>", " "); // <> 태그형식을 모두 공백으로 대체
    }

    public static void main(String arg[]) {
        try {
            new IndexerDoc();
        } catch (Exception ex) {
            System.out.println("Cannot Start");
        }
    }
}



참고 사이트 : http://computergodzilla.blogspot.kr


※ 위 내용은, 여러 자료를 참고하거나 제가 주관적으로 정리한 것입니다.
   잘못된 정보나 보완이 필요한 부분을, 댓글 또는 메일로 보내주시면 많은 도움이 되겠습니다.
05 28, 2013 19:17 05 28, 2013 19:17


Trackback URL : http://develop.sunshiny.co.kr/trackback/914

Leave a comment


Recent Posts

  1. HDFS - Python Encoding 오류 처리
  2. HP - Vertica ROS Container 관련 오류...
  3. HDFS - Hive 실행시 System Time 오류
  4. HP - Vertica 사용자 쿼리 이력 테이블...
  5. Client에서 HDFS 환경의 데이터 처리시...

Recent Comments

  1. It's amazing to pay a visit this s... 대구유흥 01 18,
  2. 안녕하세요^^ 배그핵
  3. 안녕하세요^^ 도움이 되셨다니, 저... sunshiny
  4. 정말 큰 도움이 되었습니다.. 감사합... 사랑은
  5. 네, 안녕하세요. 댓글 남겨 주셔서... sunshiny

Recent Trackbacks

  1. pet friendly flats to rent in london pet friendly flats to rent in london 18 01
  2. los cabos luxury vacation los cabos luxury vacation 18 01
  3. get redirected here get redirected here 18 01
  4. Mysql - mysql 설치후 Character set... 멀고 가까움이 다르기 때문 %M

Calendar

«   01 2020   »
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31  

Bookmarks

  1. 위키피디아
  2. MysqlKorea
  3. 오라클 클럽
  4. API - Java
  5. Apache Hadoop API
  6. Apache Software Foundation
  7. HDFS 생태계 솔루션
  8. DNSBL - Spam Database Lookup
  9. Ready System
  10. Solaris Freeware
  11. Linux-Site
  12. 윈디하나의 솔라나라

Site Stats

TOTAL 2817451 HIT
TODAY 4 HIT
YESTERDAY 647 HIT