# 루씬 문서 인덱싱(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

« Previous : 1 : ... 110 : 111 : 112 : 113 : 114 : 115 : 116 : 117 : 118 : ... 648 : Next »

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. 안녕하세요^^ 배그핵
  2. 안녕하세요^^ 도움이 되셨다니, 저... sunshiny
  3. 정말 큰 도움이 되었습니다.. 감사합... 사랑은
  4. 네, 안녕하세요. 댓글 남겨 주셔서... sunshiny
  5. 감사합니다 많은 도움 되었습니다!ㅎㅎ 프리시퀸스

Recent Trackbacks

  1. church building construction church building construction %M
  2. wireless clocks transmitter wireless clocks transmitter %M
  3. how to build a metal building how to build a metal building %M
  4. builder builder %M
  5. social media management company social media management company %M

Calendar

«   12 2019   »
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 2781617 HIT
TODAY 1200 HIT
YESTERDAY 1360 HIT