package org.fastcatsearch.datasource.reader;
import org.fastcatsearch.datasource.SourceModifier;
import org.fastcatsearch.datasource.reader.annotation.SourceReader;
import org.fastcatsearch.ir.common.IRException;
import org.fastcatsearch.ir.config.SingleSourceConfig;
import org.fastcatsearch.util.HTMLTagRemover;
import org.fastcatsearch.util.ReadabilityExtractor;
import org.fastcatsearch.util.WebPageGather;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Created by 전제현 on 2016-02-22.
* 설정에서 URL List를 읽어와 해당 URL의 내용을 파싱하여 색인한다. (웹페이지 색인)
*/
@SourceReader(name="WEBPAGE")
public class WebPageSourceReader extends SingleSourceReader<Map<String, Object>> {
protected static Logger logger = LoggerFactory.getLogger(WebPageSourceReader.class);
private String[] urlList;
private Map<String, Object> dataMap;
private Pattern p;
private int lineNum;
private WebPageGather webPageGather;
private static ReadabilityExtractor extractor = new ReadabilityExtractor();
public WebPageSourceReader() {
super();
}
public WebPageSourceReader(String collectionId, File filePath, SingleSourceConfig singleSourceConfig, SourceModifier<Map<String, Object>> sourceModifier, String lastIndexTime) throws IRException {
super(collectionId, filePath, singleSourceConfig, sourceModifier, lastIndexTime);
}
@Override
public void init() throws IRException {
dataMap = null;
p = Pattern.compile("<title>(?s)(.*)(?s)</title>",Pattern.CASE_INSENSITIVE);
lineNum = 0;
webPageGather = new WebPageGather();
String urlListText = getConfigString("urlList").toString();
urlList = urlListText.split("\n");
}
@Override
public boolean hasNext() throws IRException {
String urlInfo = readURLInfo();
dataMap = new HashMap<String, Object>();
if(urlInfo == null)
return false;
String[] tmps = urlInfo.split("\t");
for (int count = 0; count < tmps.length; count++) {
tmps[count] = tmps[count].replaceAll("\r", "");
}
if (tmps.length >= 1 && tmps.length < 6) {
String source;
if (tmps.length <= 2) {
source = webPageGather.getLinkPageContent(tmps[0], "utf-8", "get");
} else if (tmps.length >= 3) {
if (tmps[2] == null || tmps[2].equals("")) {
source = webPageGather.getLinkPageContent(tmps[0], "utf-8", "get");
} else {
source = webPageGather.getLinkPageContent(tmps[0], tmps.length > 2 ? tmps[2] : "utf-8", "get");
}
} else {
logger.error("There is error in url list parameter at line {}", lineNum);
return false;
}
// ID값 입력, URL 정보 한 줄을 읽어올 때마다 1씩 증가한다. (필드 ID)
dataMap.put("id", lineNum);
dataMap.put("source", source);
// 타이틀, 텍스트 파일에 미리 입력해 둔 타이틀이 있다면 해당 값을 가져오고, 그게 아니라면 타이틀 태그에서 값을 가져온다. (필드 TITLE)
if (tmps.length == 1) {
Matcher m = p.matcher(source);
String title = "";
if (m.find()) {
title = m.group(1);
} else {
title = "";
}
dataMap.put("title", title);
} else {
if (tmps[1] == null || tmps[1].equals("")) {
Matcher m = p.matcher(source);
String title = "";
if (m.find()) {
title = m.group(1);
} else {
title = "";
}
dataMap.put("title", title);
} else {
dataMap.put("title", tmps[1]);
}
}
// 웹페이지 내용을 파싱 후 텍스트에 해당되는 내용만을 추출한다. 필드 CONTENT에 저장한다. 페이지 접근이 되지 않을 경우 파싱하지 않는다.
String extracted = null;
try {
extracted = extractor.extract(source);
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
if(extracted == null) {
extracted = HTMLTagRemover.clean(source);
}
dataMap.put("content", extracted);
/*
* URL 값을 색인 시 저장한다. 해당 값은 텍스트 파일에 입력한 주소를 그대로 가져온다.
* 4번째 파라미터로 하이퍼링크 용의 주소를 별도로 입력했을 경우
* */
if (tmps.length == 4) {
dataMap.put("url", tmps[0]);
dataMap.put("link", tmps[3]);
} else {
dataMap.put("url", tmps[0]);
dataMap.put("link", tmps[0]);
}
/*
* 2016-03-02
* 별도의 다섯 번째 파라미터를 받는 경우 추가
* */
if (tmps.length == 5) {
dataMap.put("etc", tmps[4]);
}
} else {
logger.error("There is error in url list file at line {}", lineNum);
return false;
}
return true;
}
/*
* 설정에 입력된 파일을 불러와 파싱을 할 URL 정보를 가져온다.
* 입력할 정보는 URL,제목,인코딩 설정,링크주소 이다.
* URL 이외에는 필수 입력 항목이 아니며, 제목의 경우 입력하지 않으면 title 태그에서 제목을 가져오고, 인코딩 설정은 입력하지 않을 시 기본적으로 UTF-8이다.
* */
private String readURLInfo() throws IRException {
String line = "";
if (lineNum >= urlList.length) {
return null;
}
if (urlList[lineNum] == null) {
return null;
}
String[] splited = urlList[lineNum].split(",");
line = "";
for (int cnt = 0; cnt < splited.length; cnt++) {
line += splited[cnt] + "\t";
}
lineNum++;
return line;
}
@Override
protected Map<String, Object> next() throws IRException {
return dataMap;
}
@Override
protected void initParameters() {
registerParameter(new SourceReaderParameter("urlList", "URL List", "URL List for Webpage Parsing. (URL,TITLE,Encoding,Link URL)"
, SourceReaderParameter.TYPE_TEXT, true, null));
}
}