스트링부트 웹 크롤링 하는 방법[Jsoup]
Jsoup 사용하는 방법
Jsoup는 자바 언어로 HTML을 쉽게 파싱할 수 있게 도와주는 라이브러리이다.
1.Maven 저장소에서 Jsoup 코드를 복사해서 pom.xml 파일에 붙여넣기 한다.
<dependencies>
<!-- 추가한 라이브러리 시작 -->
<!-- https://mvnrepository.com/artifact/org.jsoup/jsoup -->
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.13.1</version>
</dependency>
<!-- 추가한 라이브러리 끝 -->
<!-- 중략 -->
</dependencies>
의존성 관리 도구 Maven 저장소 활용하는 방법Maven이란 공통 레퍼지토리로 보통 라이브러리가 서로 연관성이 있는 경우, 연관되어 있는 라이브러리를 모두 다운 받아야하는데, 이 저장소를 활용하면 상위 라이브러리만 가져오면 하위 라이브러리도 자동으로 가져오게 된다....
Jsoup 라이브러리가 먹히지 않을 경우 STS를 다시 시작해 보세요.
2.url에서 HTML 문서 가져온다.
Document doc = Jsoup.connect(url).get();
3.HTML에서 원하는 요소를 가져온다.
Elements elem = doc.select("#articleTitle");
네이버 뉴스 기사 웹 크롤링하기
HTTP 서버와 통신하는 방법
RestTemplate는 spring 3.0부터 지원하는 HTTP 서버와 통신하는 방법 중 하나로 기계적이고 반복적인 코드를 최대한 줄여주며 json, xml 응답에 적합하다. 그 외에도 HTTP 서버와 통신하는 방법으로 자바에서는 HttpUrlConnection, okHttp, RestTemplate, Retrofit2 등을 사용할 수 있다. (파이썬에서는 requests 사용).
Jsoup만 사용해서 통신을 할 수 있으나 여기서는 RestTemplate 사용법을 익히고자 두 가지 방법을 모두 사용한 방법을 소개한다.
네이버 뉴스 기사 HTML 분석하기
정치 카테고리에 있는 뉴스 기사 제목과 기사 발행일을 크롤링하려고 합니다. 여기서 뉴스 기사 제목과 기사 발행일을 추출하기 위한 id/class 값을 분석합니다. 뉴스 기사 제목은 유일한 값인 id값 ‘articleTitle’을 사용하면 되고, 기사 발행일은 class값으로 ‘.t11’이 주어져 있는데 다른 곳에서 사용하고 있는지 document.querySelect()를 사용해서 확인해 봅니다. 여기서는 ‘.t11’가 두 군데 사용되고 있어서 [0]번째를 사용하기로 합니다.
크롤링 정보를 한번에 담을 객체 생성
package com.cos.newssave.batch;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
@Builder
@AllArgsConstructor
@Data
public class NewsTest {
private String title;
private String time;
}
RestTemplate 사용
package com.cos.newssave.batch;
import java.util.ArrayList;
import java.util.List;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.junit.jupiter.api.Test;
import org.springframework.web.client.RestTemplate;
public class NaverCrawTest {
int aidNum = 1;
@Test
public void test3() {
RestTemplate rt = new RestTemplate(); //RestTemplate 객체 생성
List<NewsTest> nts = new ArrayList<>(); //수집한 collections를 담기 위한 리스트
for(int i = 1; i < 11; i++) {
String aid = String.format("%010d", aidNum); //10자리 숫자를 만들기 위한 문자열 포맷
String url = "https://news.naver.com/main/read.naver?mode=LSD&mid=shm&sid1=100&oid=003&aid="+aid; //사용할 네이버 뉴스 기사 주소
String html = rt.getForObject(url, String.class);//해당 주소에서 html을 담아준다.
Document doc = Jsoup.parse(html);//html 문서를 Jsoup 도큐먼트에 담아준다.
Element titleElement = doc.selectFirst("#articleTitle"); //뉴스 기사 제목 요소를 가지고 온다.
Element timeElement = doc.selectFirst(".t11"); //기사 발행일 요소를 가지고 온다.
String title = titleElement.text(); //html 태그를 제거하고 텍스트만 가지고 온다.
String time = timeElement.text();
System.out.println(title);
System.out.println(time);
NewsTest nt = NewsTest.builder() //크롤링 정보를 담아줄 객체를 만든다.
.title(title)
.time(time)
.build();
nts.add(nt); //리스트에 객체를 더해준다.
aidNum++; //반복문을 돌 때마다 기사 아이디를 더해준다.
}
//System.out.println(nts.size());
//assertTrue(nts.size() == 11); JUnit으로 테스트 통과하는지 알 수 있다.
}
}
<결과 화면>
RestTemplate 미사용
package com.cos.newssave.batch;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.junit.jupiter.api.Test;
import org.springframework.web.client.RestTemplate;
public class NaverCrawTest {
int aidNum = 1;
@Test
public void test4() {
RestTemplate rt = new RestTemplate();
List<NewsTest> nts = new ArrayList<>(); // collections
for (int i = 1; i < 11; i++) {
String aid = String.format("%010d", aidNum);
String url = "https://news.naver.com/main/read.naver?mode=LSD&mid=shm&sid1=100&oid=003&aid=" + aid;
try {
Document doc = Jsoup.connect(url).get();
Element titleElement = doc.selectFirst("#articleTitle");
Element timeElement = doc.selectFirst(".t11");
String title = titleElement.text();
String time = timeElement.text();
System.out.println(title);
System.out.println(time);
NewsTest nt = NewsTest.builder().title(title).time(time).build();
nts.add(nt);
aidNum++;
} catch (IOException e) {
e.printStackTrace();
}
}
System.out.println(nts.size());
}
}
<결과 화면>

