JSOUP 으로만 웹 크롤링하기는 아래 링크를 참조하세요!
- http://derveljunit.tistory.com/280
# 안읽어도 좋은 서론(넋두리)
파이썬으로 웹 크롤러를 만들어보려 예제까지 만들어 보았건만
중대한 문제에 봉착한다.
파이썬의 뷰티풀솝으로 가져온 HTML은 그 html에서 참조하는 또 다른 html을 가져오지 못한다는 것.
왜인지도 모르겠고, 찾기에는 시간이 아까워서 그냥 자바로 만들자고 생각했다 ^^;;;
파이썬이 좋은 점은 C를 활용해서 속도가 빠르다는 것과 간단한 소스 코드, 그리고 범용적인 라이브러리 사용인데, 사실 다른 언어에도 다 라이브러리가 있다.
소스코드가 복잡하다? 자바도 점점 간략화 되어가고 있다.
오히려 편한 언어가 생산성이 더 좋은 법(이렇게 말하면서 파이썬 툴과 파이썬을 삭제한다. 사실 문법이 마음에 안들어 배우기도 귀찮아...)
그래서 간단한게 만들어보았다.
# 본론(feat. 빈약한 예제)
아파치는 사랑이다.
아파치에서 제공하는 HTTP 라이브러리로 쉽게 HTML을 가져올 수 있다.
사용할 라이브러리는 아파치가 제공하는 http 관련 라이브러리와
DOM을 파싱할 Jsoup 라이브러리
1. 다운로드
Download 는 https://hc.apache.org/downloads.cgi 에서
최신 버전의 binary형태의 http-core나 http-client 둘중 아무거나 받으면 된다.
받은 압축내에 lib 폴더를 보면 아파치가 친절하게 다 때려 넣어주었다.
사용할 라이브러리는
- commons-logging-1.2.jar
- httpclient-4.5.2.jar
- httpcore-4.4.4.jar
Jsoup은 https://jsoup.org/download 여기서 다운받기
2. 라이브러리 추가
간략히 소개만. 모르겠으면 구글링
1) 자바 프로젝트(생짜 프로젝트)는 소스에 라이브러리 추가하고 Build-path 추가
2) 웹 프로젝트는 WEB-INF / LIB / 밑에 추가 및 Build-path 추가
3) 스프링 프레임워크는 dependency 추가 -> 자세한 건 구글링 ㄱㄱ
3. 소스 코드 및 예제
기본적으로 Jsoup 의 Connect 함수를 통해서 데이터를 가져올 수 있지만, 파이썬에서 값을 가져올때와 마찬가지로 진짜 생짜 스크립트와 HTML만 가져온다. 그래서 보조로 httpclient를 통해 가져온 데이터를 Jsoup에 담아서 크롤링을 한다.
package batch;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.impl.client.HttpClientBuilder;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
public class JavaWebCrawler {
public static String getCurrentData(){
SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
return sdf.format(new Date());
}
public static void main(String[] args) throws ClientProtocolException, IOException {
// 1. 가져오기전 시간 찍기
System.out.println(" Start Date : " + getCurrentData());
// 2. 가져올 HTTP 주소 세팅
HttpPost http = new HttpPost("http://finance.naver.com/item/coinfo.nhn?code=045510&target=finsum_more");
// 3. 가져오기를 실행할 클라이언트 객체 생성
HttpClient httpClient = HttpClientBuilder.create().build();
// 4. 실행 및 실행 데이터를 Response 객체에 담음
HttpResponse response = httpClient.execute(http);
// 5. Response 받은 데이터 중, DOM 데이터를 가져와 Entity에 담음
HttpEntity entity = response.getEntity();
// 6. Charset을 알아내기 위해 DOM의 컨텐트 타입을 가져와 담고 Charset을 가져옴
ContentType contentType = ContentType.getOrDefault(entity);
Charset charset = contentType.getCharset();
// 7. DOM 데이터를 한 줄씩 읽기 위해 Reader에 담음 (InputStream / Buffered 중 선택은 개인취향)
BufferedReader br = new BufferedReader(new InputStreamReader(entity.getContent(), charset));
// 8. 가져온 DOM 데이터를 담기위한 그릇
StringBuffer sb = new StringBuffer();
// 9. DOM 데이터 가져오기
String line = "";
while((line=br.readLine()) != null){
sb.append(line+"\n");
}
// 10. 가져온 아름다운 DOM을 보자
System.out.println(sb.toString());
// 11. Jsoup으로 파싱해보자.
Document doc = Jsoup.parse(sb.toString());
// 참고 - Jsoup에서 제공하는 Connect 처리
Document doc2 = Jsoup.connect("http://finance.naver.com/item/coinfo.nhn?code=045510&target=finsum_more").get();
// System.out.println(doc2.data());
// 12. 얼마나 걸렸나 찍어보자
System.out.println(" End Date : " + getCurrentData());
}
}
아래는 실행 결과
Start Date : 2016.07.23 14:36:06
<!-- global include -->
"... dom 구조 및 스크립트 이므로 중략 ..."
</body>
</html>
End Date : 2016.07.23 14:36:08
대략 2초정도 걸린다.
여기에 크롤링할 데이터에 대한 로직까지 심으면 대략 3~4초 걸리지 않을까 예상해본다.
# 결론
사실 난 Jsoup안 쓰고 문법이 편하고 익숙한 Jquery로 크롤링할거 였는데
Jsoup은 자바로만 처리할 사람이 있을 거 같아 넣어봤다...
자세한 Jsoup을 활용하는 예제는 jsoup 본 사이트를 참조.
httpclient로 jquery까지 html을 가져올 인터페이스 역할만 한다.
dom 파싱하는데에는 jquery 만한게 없다고 본다.
왜냐 내가 익숙하니까...
# 후기
1. 이글을 쓰고 몇 분뒤에 깨달은 건데 가져오려는 데이터가 안나왔던 이유는
iframe 값이었기 때문에 그랬다... 자나깨나 iframe 조심...
2. python 보다 느리다
'Java & Spring > Java 문법' 카테고리의 다른 글
[Java Stream] double[] 을 List<Double>로 / List<Double>을 double[]로 바꾸기 (0) | 2020.02.17 |
---|---|
Java Reflection과 사용에 대한 고찰 (0) | 2017.01.15 |
[Java] replaceAll 에서 Illegal group reference 처리 (0) | 2016.02.12 |
[Java Util] 문자열 내 HTML 태그 사용 특수문자 치환 (0) | 2016.02.12 |
[Java] GSON 을 이용한 JSON to Generic/VO 또는 GenericVO to JSON (0) | 2015.12.30 |
WRITTEN BY