JSP

[JSP] jsoup 를 이용한 크롤링 및 MYSQL 데이터 베이스 저장

allempty_sheep 2024. 8. 1. 09:39
반응형

라이브러리 파일을 받아주자.

https://mvnrepository.com/artifact/org.jsoup/jsoup/1.18.1

 

아래 멜론 차트 데이터를 가져와 볼 것이다.

https://www.melon.com/chart/index.htm

 

Melon

음악이 필요한 순간, 멜론

www.melon.com

 

먼저 데이터를 가져와 보자.

 

가수의 이름과 곡 제목을 가져와야 한다.

 

해당 태그를 우측클릭해서 copy 를 보면 다양한 태그 카피가 나오는데

 

 

selector 를 카피하여 곡 이름과 가수를 가져와 보자.

 

곡 이름

#lst50 > td:nth-child(6) > div > div > div.ellipsis.rank01 > span > a

 

가수

#lst50 > td:nth-child(6) > div > div > div.ellipsis.rank02 > a

 

그런데 50위 초과 100위 이하는

#lst100 으로 시작하기 때문에

공통되는 부분은 뒷부분이다.

 

jsoup 를 이용하여 데이터를 가져오자.

rank01, rank02 가 붙은 부분이 각자 다르니 해당 값에서 시작 해 주었다.

	String crawlingUrl = "https://www.melon.com/chart/index.htm";
	Document doc = Jsoup.connect(crawlingUrl).get();
	Elements titles = doc.select("div.ellipsis.rank01").select("span").select("a");
	Elements artists = doc.select("div.ellipsis.rank02 > a");

 

jstl으로 사용해 주기 위해 선언한다.

		pageContext.setAttribute("titles", titles);
		pageContext.setAttribute("artists", artists);

 

보여주기위한 View 이다.

	<div class="body-main">
		<div class="container">
			<div class="row">
				<c:forEach items="${titles}"  var="title" varStatus="status">
						<div class="col-4">${status.index +1}</div>
						<div class="col-4">${title}</div>
						<div class="col-4">${artists[status.index]}</div>
				</c:forEach>
			</div>
		</div>
	</div>

 

최종 코드는 다음과 같다.

	<%
		String crawlingUrl = "https://www.melon.com/chart/index.htm";
		Document doc = Jsoup.connect(crawlingUrl).get();
		Elements titles = doc.select("div.ellipsis.rank01").select("span").select("a");
		Elements artists = doc.select("div.ellipsis.rank02 > a");
		
		pageContext.setAttribute("titles", titles);
		pageContext.setAttribute("artists", artists);
	%>
	<div class="body-main">
		<div class="container">
			<div class="row">
				<c:forEach items="${titles}"  var="title" varStatus="status">
						<div class="col-4">${status.index +1}</div>
						<div class="col-4">${title}</div>
						<div class="col-4">${artists[status.index]}</div>
				</c:forEach>
			</div>
		</div>
	</div>

 

화면을 보면 다음과 같은 데이터들이 나올 것이다.

 

데이터베이스에 데이터를 넣어보자.

테이블 구조는 다음과 같다.

CREATE TABLE `songs` (
  `num` int NOT NULL,
  `title` varchar(100) NOT NULL,
  `artist` varchar(100) NOT NULL,
  `regdate` datetime NOT NULL,
  PRIMARY KEY (`title`,`regdate`)
)

 

해당데이터를 데이터 베이스에 넣기 위해서 DAO를 작성 해 주었다.

데이터 타입은 Elements 로 들어오게 된다.

Elements를 돌면서 안의 데이터의

1. index를 이용하여 랭크를 정하고

2. Title 을 지정,

3. artists 에서 현재 index 와 같은 위치의 값을 가져와 데이터 베이스에 연속해서 저장한다.

중복으로 데이터가 들어올 시 num(rank) 값을 업데이트 하게 하였다.

해당 테이블의 키 값은 타이틀(노래제목), regdate(날짜) 이다.

	public int insertSong(Elements titles, Elements artists) {
		int rs = 0;
		
		for(Element title: titles) {
			int rankData = titles.indexOf(title)+1;
			String titleData = title.text();
			String artistData = artists.get(titles.indexOf(title)).text();
			
			System.out.println(rankData);
			System.out.println(titleData);
			System.out.println(artistData);
			
			String sql = "INSERT INTO songs VALUES (?, ?, ?, DATE(NOW())) ON DUPLICATE KEY UPDATE num = (?)";
			try {
				psmt = con.prepareStatement(sql);
				psmt.setInt(1, rankData);
				psmt.setString(2, titleData);
				psmt.setString(3, artistData);
				psmt.setInt(4, rankData);
				rs = psmt.executeUpdate();
				
				
			} catch (Exception e) {
				// TODO: handle exception
				e.printStackTrace();
			}
		}

		/*
		
		*/
		return rs;
	}

 

이후 jsp 파일에서 DAO 를 호출하여 함수를 호출 한다.

 

총 코드는 다음과 같다.

jsp

	<%
		String crawlingUrl = "https://www.melon.com/chart/index.htm";
		Document doc = Jsoup.connect(crawlingUrl).get();
		Elements titles = doc.select("div.ellipsis.rank01").select("span").select("a");
		Elements artists = doc.select("div.ellipsis.rank02 > a");
		
		pageContext.setAttribute("titles", titles);
		pageContext.setAttribute("artists", artists);
		
		System.out.println(titles);
		songsDAO songsDAO = new songsDAO(application);
		songsDAO.insertSong(titles, artists);
	%>
	<div class="body-main">
		<div class="container">
			<div class="row">
				<c:forEach items="${titles}"  var="title" varStatus="status">
						<div class="col-4">${status.index +1}</div>
						<div class="col-4">${title}</div>
						<div class="col-4">${artists[status.index]}</div>
				</c:forEach>
			</div>
		</div>
	</div>

 

DAO

import java.util.ArrayList;
import java.util.Arrays;

import javax.servlet.ServletContext;

import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import common.MDBConnect;

public class songsDAO extends MDBConnect {
	public songsDAO (ServletContext application) {
		super(application);
	}
	
	public int insertSong(Elements titles, Elements artists) {
		int rs = 0;
		
		for(Element title: titles) {
			int rankData = titles.indexOf(title)+1;
			String titleData = title.text();
			String artistData = artists.get(titles.indexOf(title)).text();
			
			System.out.println(rankData);
			System.out.println(titleData);
			System.out.println(artistData);
			
			String sql = "INSERT INTO songs VALUES (?, ?, ?, DATE(NOW())) ON DUPLICATE KEY UPDATE num = (?)";
			try {
				psmt = con.prepareStatement(sql);
				psmt.setInt(1, rankData);
				psmt.setString(2, titleData);
				psmt.setString(3, artistData);
				psmt.setInt(4, rankData);
				rs = psmt.executeUpdate();
				
				
			} catch (Exception e) {
				// TODO: handle exception
				e.printStackTrace();
			}
		}

		/*
		
		*/
		return rs;
	}
}