HTML 크롤링하여 스크래핑할 때 Jsoup 을 많이 사용합니다.
하지만 Jsoup에는 크게 두가지 문제가 있어 보입니다.
1. 큰 HTML 파일을 크롤링 제대로 하지 못합니다.
2. 잘못된 HTML 파일의 경우 텍스트만 발라내다가 행(Hang)이 걸립니다. 21세기에 이런 황당한 일이...
1번 문제는 크롤링은 HttpClient 같은 오픈소스를 이용하여 해결할 수 있습니다.
2번 문제는 Swing에 있는 모듈로 처리할 수 있습니다. 대충 아래처럼 하면 HTML에서 텍스트를 얻어낼 수 있습니다.
StringBuilder sb = new StringBuilder();
ParserDelegator parserDelegator = new ParserDelegator();
HTMLEditorKit.ParserCallback parserCallback = new HTMLEditorKit.ParserCallback() {
public void handleText(final char[] data, final int pos) {
sb.append(String.valueOf(data)).append(" ");
}
public void handleStartTag(HTML.Tag tag, MutableAttributeSet attribute, int pos) { }
public void handleEndTag(HTML.Tag t, final int pos) { }
public void handleSimpleTag(HTML.Tag t, MutableAttributeSet a, final int pos) { }
public void handleComment(final char[] data, final int pos) { }
public void handleError(final java.lang.String errMsg, final int pos) { }
};
parserDelegator.parse(reader, parserCallback, true);
return sb.toString();
그런데 HttpClient로 크롤링할 때 생각지도 못한 문제가 있습니다.
크롤링하다가 불안정한 사이트 같은 경우 행(Hang)이 걸릴 때가 있습니다. 놀랍게도 timeout을 설정해도 문제는 해결되지 않습니다. 이런 경우 timeout이 적용되지 않아 보입니다. 접속이 되고 실제 데이터를 전송받는데... 데이터를 중간에 받지 못하는 경우 예외도 발생하지 않고 행(Hang)이 걸리는 듯 싶습니다. 21세기에 ... 만약에 rabbitmq Listener에서 이런 행이 발생하면 rabbitmq에게 ack를 제대로 하지 못해 큐에서 데이터를 받지 못하는 불상사가 발생합니다. 이런 불상사가 발생하면 관리화면에서 fetch를 시도해도 데이터를 받지 못하는 문제가 발생합니다. @.@
이런 때에는 Timer를 하나 띄워 Hard한 Timeout을 설정해야 합니다. 아래 처럼...
HttpGet getMethod = new HttpGet(url);
int hardTimeout = 30; // seconds
TimerTask task = new TimerTask() {
@Override
public void run() {
if (getMethod != null) {
getMethod.abort();
}
}
};
new Timer(true).schedule(task, hardTimeout * 1000);
놀랍지요. 21세기 Hang이 걸리는 프로그램이 있다는 게... @.@