Java

[Java] Jsoup 라이브러리를 이용한 웹 크롤링

나루나른 2024. 4. 1. 21:25

웹 스크래핑

웹 스크래핑(scraping)이란 특정한 웹 사이트에서 필요한 데이터를 수집하는 방법이다. 웹 크롤링보다는 좁은 범위의 데이터를 수집하는데 주로 사용된다. 온라인 쇼핑몰의 특정한 상품의 정보나, 뉴스 사이트의 최신 기사를 수집하는 등 스크래핑은 특정한 웹 사이트에서 필요한 데이터를 추출하는 데 초점을 둔다는 차이점이 있다.

 

웹 크롤링

웹 크롤링(crawling)이란  웹 즉 인터넷 상의 정보들을 탐색하고 수집하는 작업들을 의미한다. 인터넷 상의 모든 페이지를 방문하며, 각 페이지의 링크를 따라가면서 자동으로 데이터를 수집한다. 크롤링은 대부분의 검색엔진에서 사용되며, 구글이나 네이버와 같은 검색엔진 들도 검색에 대한 결과를 보여줄 때 크롤러를 사용하여 인덱싱 작업을 수행한다. 크롤링은 스크래퍼와 다르게 특정한 웹 페이지가 아닌 URL을 타고다니며 반복적으로 데이터를 가져오는 과정(데이터 색인)이 진행된다.

 

※ 크롤러 : 규칙에 따라 자동으로 웹 문서를 탐색하는 컴퓨터 프로그램

※ 인덱싱 작업 :  데이터를 효율적으로 검색, 조회할 수 있도록 데이터베이스, 검색 엔진, 파일 시스템 등에서 사용하는 과정

(예:  책의 색인이나 사전의 알파벳 순 색인과 비슷한 역할이다.)

 

웹 크롤링에 대한 주의사항이 몇가지 존재하지만 여기서는 생략하겠다.(자세한 설명은 출처 링크를 통해)

 

자바에서 사용하는 웹 크롤링 라이브러리로는 대표적으로 'Jsoup'가 존재한다. 

 

'Jsoup'는 정적데이터를 비교적으로 빠르게 수집할 수 있지만 브라우저가 아닌 HTTP 프로토콜의 HTTP Request(HTTP 요청)를 사용하기 때문에 동적 데이터(실시간으로 변화하는)를 수집하기 위해서는 제한 사항이 있다. 

Jsoup는 보통 자바에서 HTML 문서를 파싱(데이터 분석), DOM 조작(웹페이지를 구성하는 프로세서), CSS 선택자를 통한 데이터 추출 등의 기능을 제공하는 라이브러리이며, 매우 직관적이며 쉽게 웹 페이지로부터 데이터를 추출할 수 있게 해준다. 

 

※ DOM 조작 : HTML로 동작하는 해당 문서에서 특정 요소나 그룹을 찾거나, 새로운 요소의 추가 및 수정, 삭제 등을 말하는 것이다.

(예 :  select 등의 검색, <p> 태그를 <div> 태그에 새로 추가하는 것 등)

 

그럼 자바 기반의 HTML parser인 Jsoup 라이브러리로 크롤링 하는 방법을 알아보자.

parser : 인터프리터나 컴파일러의 구성 요소 가운데 하나로, 입력 토큰에 내재된 자료 구조를 빌드하고 문법을 검사하는 도구다.


Jsoup 다운로드는 해당 링크를 통해 할 수 있다.

 https://jsoup.org/download -> jsoup-1.17.2.jar 

 

 

프로젝트를 생성하고 외부라이브러리(Jsoup) 추가

JavaEE를 통해 Dynamic Web Project를 생성하고 라이브러리를 추가했다.

외부 라이브러리의 위치

 

위에서 다운받은 jsoup-1.17.2.jar 파일을 라이브러리 파일( lib)에 추가해주어야 한다.

위의 사진처럼 경로를 지정해주면 끝! 직접 JavaEE에서 끌어다가 추가해줘도 된다.

 

jsoup의 핵심 클래스

본격적으로 jsoup를 사용하기 전에 알아야될 핵심 클래스들이다.

 

1) Document 클래스

 : 연결해서 얻어온 HTML 전체 문서

 

2) Elements 클래스

 : Element가 모인 자료형

 

3) Element 클래스

 : Document의 HTML 요소

 

해당 클래스 외 다른 부분은 jsoup의 공식 문서를 참조하길 바란다.

https://jsoup.org/ (jsoup 공식문서)

 

 

jsoup를 이용한 크롤링

jsoup를 이용한 본격적인 크롤링 방법이다. 해당 문제는 전자정부 프레임워크 웹페이지의 공지사항 제목을 크롤링하는 방법이다.

 

1) 공지사항 페이지의 주소와 접근하기 위한 파라미터 값을 String 문자열 클래스를 이용해 각각 URL 변수와 parms 변수에 저장했다.

//공지사항의 기본 웹주소를 저장 
String URL = "https://www.egovframe.go.kr/home/ntt/nttList.do";
//공지사항 페이지에 접근하기 위한 고정 파라미터 값을 문자열 형태로 저장한다.
//해당 파라미터에는 검색 키워드(searchKey, searchValue), 메뉴 번호(menuNo), 게시판 ID(bbsId)가 포함되어 있다.
String params = "?searchKey=&searchValue=&menuNo=74&bbsId=6";

 

 

2)  for문을 이용해 각각의 페이지를 순회하며 데이터를 가져온다.

여기서 p의 값이 10씩 증가하는 이유는 홈페이지의 게시물의 수에 따라 결정된다. 해당 전자 정부 프레임워크 공지사항의 경우 한 페이지의 게시물이 10개이기 때문에 10씩 증가한다. 만약 공지사항의 게시글 20개가 한 페이지라면 p의 값 또한 20씩 증가시켜야한다.(페이징의 개념)

for(int p=0; p<=220; p+=10) {
String page = "&pagerOffset=" + p;
//document 객체는 html문서의 전체를 나타낸다. 
//해당 객체를 통해 문서의 구조, 데이터 속성등에 접근 및 조작이 가능함.
Document doc = Jsoup.connect(URL+params+page).get();

 

- Jsoup.connect(URL) : 페이지 주소의 문자열을 주소화 한다.- get() : 주소화된 페이지의 주소를 가져온다.즉 Jsoup.connect.get()은 각 페이지에 해당하는 HTML 문서를 가져온다는 뜻이다.

 

불러온 페이지의 소스

 

출력하면 아래와 같이 페이지 소스의 전체가 불러와졌다.

 

이와 비슷한 예제를 통해 자세히 알아보자 

아이티윌 웹페이지의 1~5p의 공지사항 제목만 크롤링하는 방법이다.

 

1) 위의 방법과 같이 페이지의 주소와 접근하기 위한 파라미터 값을 String 문자열 클래스를 이용해 각각 URL 변수와 parms 변수에 저장한다.

String URL = "https://www.itwill.co.kr/cmn/board/BBSMSTR_000000000071/bbsList.do";
String params = "?bbsId=BBSMSTR_000000000071&currentMenuNo=1031100&searchCondition=0&searchKeyword=";

 

 

2) for 문을 이용해 1~5p 페이지를 순회하며 데이터를 검색한다. 그리고 해당하는 데이터를 페이지를 나타내는 변수 p에 저장한다. 

//for 문을 이용한 페이지 별 접근 1~5페이지를 순회한다.
for(int p=1; p<=5; p++) { 
//URL에 추가되는 쿼리 스트링(query string)의 일부로, 웹 페이지 내의 특정 페이지 번호를 지정하는 데 사용 'p'는 페이지의 번호를 나타내는 변수다.
String page = "&pageIndex=" + p; 
//System.out.println(params + page);

 

 

 

3) css 선택자를 사용해 특정 공지사항의 제목만을 선택하는 방법이다. 이 선택자는 클래스명이 'bgcol01' 인 요소의 자식 중 td 태그이면서 두 번째 자식인 요소들을 선택한다. 공지사항의 제목이 위치하는 셀을 의미한다.

Elements elements = doc.select(".bgcol01>td:nth-child(2)");

 

 

4) 그리고 선택한 요소들(Elements)에서 각 요소를 순회하며 text() 메소드를 사용하여 텍스트 내용(제목) 만을 추출하여 출력한다.

for(Element element : elements) {
System.out.println(element.text());
}//for end

 

Elements 클래스

 - .select() : Document 클래스로 담은 HTML문의 CSS 쿼리문을 불러오는 기능이다. 여기서는 클래스명이 'bgcol01' 인 요소의 자식 중 td 태그이면서 두 번째 자식인 요소들을 불러요는 용도로 사용된다.

 - Element 클래스

 - .text() : Element 클래스로 담아진 각각의 요소를 텍스트화한다.

 

 

해당 크롤링의 출력결과이다.

 

 

관련 출처 : 

https://www.cloudflare.com/ko-kr/learning/bots/what-is-a-web-crawler/

 

https://blog.hectodata.co.kr/crawling_vs_scraping/ 

 


https://velog.io/@ehddnr7355/%EC%9B%B9-%EC%8A%A4%ED%81%AC%EB%9E%98%ED%95%91%EC%9D%98-%EA%B0%9C%EB%85%90%EA%B3%BC-%EC%8B%A4