본문 바로가기

programming/Gukbi

국비 교육 81일차 - xml, json 파싱

728x90
반응형

배운건 service먼저 배웠지만 블로깅은 파싱부터 정리

 

xml 파싱을 먼저 배웠는데, 이게 더 간단했다. 

먼저 xml 파싱을 할 수 있는 사이트 주소를 찾아서 가져온다. 

newssearch.naver.com/search.naver?where=rss&query=%EB%89%B4%EC%8A%A4

네이버 뉴스에서 내용을 긁어오는 작업을 해볼까 한다. 

 

xml을 파싱하기 위해서는 구조에 대한 이해가 필요한데, 여기서는

<rss>

 <channel>

  <item>

클래스 순서대로 정렬되어 있다. 

 

클래스 역시 순서대로 만들어 줬다. 

 

Rss 클래스

package com.sist.dao;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Rss {
	private Channel channel=new Channel();

	public Channel getChannel() {
		return channel;
	}

	public void setChannel(Channel channel) {
		this.channel = channel;
	}
	
	
}

 

 

Channel  클래스

Item 클래스는 여개 변수를 가지고 있기 때문에 List로 데이터형을 잡아줬다.

 

package com.sist.dao;
import java.util.*;
public class Channel {
	private List<Item> item=new ArrayList<Item>();

	public List<Item> getItem() {
		return item;
	}

	public void setItem(List<Item> item) {
		this.item = item;
	}
	
}

 

Item 클래스

package com.sist.dao;
// java.xml.bind => 1.8까지만 사용이 가능
public class Item {
	private String title;
	private String description;
	private String pubDate;
	private String author;
	private String link;
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
	public String getDescription() {
		return description;
	}
	public void setDescription(String description) {
		this.description = description;
	}
	public String getPubDate() {
		return pubDate;
	}
	public void setPubDate(String pubDate) {
		this.pubDate = pubDate;
	}
	public String getAuthor() {
		return author;
	}
	public void setAuthor(String author) {
		this.author = author;
	}
	public String getLink() {
		return link;
	}
	public void setLink(String link) {
		this.link = link;
	}
	
}

 파싱할 정보들을 변수로 설정해줬다. 

 

이렇게 긁어올 클래스 셋팅을 해놓으면 manager파일에서 데이터 수집해올 수 있는 메소드를 작성한다. 

package com.sist.manager;


import org.springframework.stereotype.Component;

import com.sist.dao.Item;
import com.sist.dao.Rss;

import java.util.*;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;

import java.net.*;
@Component
public class NewsManager {
	public List<Item> naverNewsData(String fd)
	{
		List<Item> list = new ArrayList<Item>();
		try
		{
			String strUrl="http://newssearch.naver.com/search.naver?where=rss&query="
					+URLEncoder.encode(fd, "UTF-8");
			URL url=new URL(strUrl);
			// 파싱
			JAXBContext jb=JAXBContext.newInstance(Rss.class);
			// XML => Java 변경
			Unmarshaller un=jb.createUnmarshaller();
			Rss rss=(Rss)un.unmarshal(url);
			list=rss.getChannel().getItem();
			
			
			
			// Java => XML 변경
			
		}catch(Exception ex){}
		return list;
	}
}

 strUrl에서 query= 뒤에 나올 부분이 검색어 자리이기 때문에 fd라는 변수를 받아오고, utf-8로 한글 인코딩을 해준다. 

JAXBContext는 xml파싱이 가능한 객체이다. rss에 저장되어 있는 정보들을 jb 변수에 담아서, 

Unmarschall 객체를 생성해준다. url주소로 파싱을 해온 뒤 list에 해당하는 정보들을 받아와서 담아준다. 

 

그리고 list를 return해주고 메소드를 종료한다. 

 

package com.sist.web;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import com.sist.dao.Item;
import com.sist.manager.*;
import java.util.*;
@Controller
public class NewsController {
	// Manager클래스
	@Autowired
	private NewsManager mgr;
	
	@RequestMapping("news/news.do")
	public String news_list(String fd, Model model)
	{
		if(fd==null)
			fd="야구";
		List<Item> list=mgr.naverNewsData(fd);
		model.addAttribute("list", list);
		return "news/news";
	}
	
}

 메소드가 완성되었으니 controller에서 처리를 해준다. 

@Autowired로 자동으로 찾아와서 메모리 할당을 해주고 시작한다. 

 

검색어인 fd, 요청을 전송하고 전달할 model을 매개변수로 받아온다

검색어가 없을 경우에는 "야구"로 초기값을 셋팅해준다. 

 

여러개의 결과값을 받아올 예정이기 때문에 List로 값을 받아온다. 

그리고 model을 통해서 보내준다. 

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<style type="text/css">
.row{
  margin: 0px auto;
}
h1 {
  text-align: center;
}
</style>
</head>
<body>
<div style="height:30px"></div>
  <div class="container">
   <h1>네이버 실시간 뉴스</h1>
  <div class="row">
  <table class="table">
   <tr>
    <td>
    <form method=post action="news.do">
     <input type=text name=fd size=15 class="input-sm">
     <input type=submit value=검색 class="btn btn-sm btn-primary">
     </form>
    </td>
   </tr>
  </table>
  <div style="height:10px"></div>
  <c:forEach var="vo" items="${list }">
  	<table class="table">
  	<tr>
  	 <td>${vo.title }</td>
  	</tr>
  	<tr>
  	 <td><a href="${vo.link}">${vo.description }</a></td>
  	</tr>
  	<tr>
  	 <td class="text-right">${vo.author }</td>
  	</tr>
  	</table>
  </c:forEach>
  </div>
  </div>
</body>
</html>

 뉴스 정보를 출력하고, 검색창에서 값을 받으면 새로운 기사들을 볼 수 있다. 

 ㅎㅎ 검색결과를 잘 보여주고 있다. 

 

그 다음은 JSON 파싱

XML보단 더 어렵다

 

JSON은 배열로 되어 있어서 따로 클래스를 만들어줄 필요없이 바로 긁어올 수 있었다. 

... 의욕을 잃게 만드는 json파싱

일단 Manager파일

 

package com.sist.json;

import org.springframework.stereotype.Component;
/*
 * 	일일 박스오피스 searchMainDailyBoxOffice.do
 * 	실시간 예매율 searchMainRealTicket.do
 * 	좌석점유율순위  searchMainDailySeatTicket.do
 * 	온라인상영관 일일 searchMainOnlineDailyBoxOffice.do
 * 
 * 	https://www.kobis.or.kr/kobis/business/main/main.do
 */
import java.util.*;
import java.net.*;
import java.io.*;
@Component
public class JSONManager {
	public String jsonRead(int no)
	{
		String json="";
		String strUrl="";
		switch(no)
		{
		case 1:
			strUrl="searchMainDailyBoxOffice.do";
			break;
		case 2:
			strUrl="searchMainRealTicket.do";
			break;
		case 3:
			strUrl="searchMainDailySeatTicket.do";
			break;
		case 4:
			strUrl="searchMainOnlineDailyBoxOffice.do";
			break;
		}
		
		try
		{
			URL url=new URL("https://www.kobis.or.kr/kobis/business/main/"+strUrl);
			HttpURLConnection conn=(HttpURLConnection)url.openConnection();
			if(conn!=null) // 사이트와 연결이 되었다면
			{
				BufferedReader br=new BufferedReader(new InputStreamReader(conn.getInputStream(),"UTF-8"));
				while(true)
				{
					String data=br.readLine();
					if(data==null) break;
					json+=data;
				}
				br.close();
			}
			System.out.println(json);
		}catch(Exception ex){}
		
		return json;
	}
	public static void main(String[] args) {
		JSONManager jm=new JSONManager();
		jm.jsonRead(1);
	}
}

 어떤 정보를 읽어올지는 no를 받아서 처리해준다. 그리고 xml과 똑같이 URL을 읽어서 가져올 준비를 해주는데, 그 전에 먼저 httpURLConnection 객체를 이용해서 사이트에 연결을 먼저 시켜준다. 

 

그리고 나서 연결이 되었다면  BufferedReader를 통해서 값을 읽어와준다. 

 

그 내용을 readLine()으로 한줄씩 읽어와서 data라는 변숭에 담아주고, 그게 null이 아니라면 미리 설정해둔 json변수에 값을 채워넣어준다. 

 

그리고 값을 확인해보면 이런식으로 하나의 배열로 나오고 있다. 

package com.sist.web;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import com.sist.json.*;
@Controller
public class JSONController {
	@Autowired
	private JSONManager jm;
	
	@RequestMapping("movie/movie_list.do")
	public String movie_movie(String no, Model model)
	{
		if(no==null)
			no="1";
		String json=jm.jsonRead(Integer.parseInt(no));
		model.addAttribute("json", json);
		return "movie/movie_list";
	}
	@RequestMapping("movie/movie.do")
	public String movie()
	{
		return "movie/movie";
	}
}

 그럼 저장한 값을 Controller에서 받아와서 jsp로 보내준다. 

 

$.ajax({
		type:'POST',
		url:'movie_list.do',
		success:function(result)
		{
			let json=JSON.parse(result);
			let res="";
			for(let i=0; i<json.length; i++)
			{
				res+="<tr>"
					+"<td>"
					+"<img src=https://www.kobis.or.kr/"+json[i].thumbUrl+" width=30 height=30></td>"
					+"<td>"+json[i].movieNm+"</td>"
					+"<td>"+json[i].director+"</td>"
					+"<td>"+json[i].genre+"</td>"
					+"<td>"+json[i].watchGradeNm+"</td>"
					+"</tr>"
			}
			$('#movie_list').html(res);
		}
	})

 ajax 코딩을 살펴보자

 

type:'POST',

 http 요청방식이다. get혹은 post방식 둘중 하나를 사용하고 있다. 

url:'movie_list.do',

 클라이언트가 요청을 보낼 서버의 url주소

 

success:function(result)
		{

 통신이 성공적으로 이루어 졌을때 아래 함수의 내용을 실행한다. 

 

let json=JSON.parse(result);
			let res="";
			for(let i=0; i<json.length; i++)
			{
				res+="<tr>"
					+"<td>"
					+"<img src=https://www.kobis.or.kr/"+json[i].thumbUrl+" width=30 height=30></td>"
					+"<td>"+json[i].movieNm+"</td>"
					+"<td>"+json[i].director+"</td>"
					+"<td>"+json[i].genre+"</td>"
					+"<td>"+json[i].watchGradeNm+"</td>"
					+"</tr>"
			}
			$('#movie_list').html(res);

 movie_list에서 받아온 result를 JSON.parse로 받아와서 json이라는 변수에 담아준다. 

json의 길이만큼 for문을 돌려서 html문장들을 작성해준다. 

 

그리고 res의 값을 html에 뿌려준다. 

버튼을 눌렀을때의 value값을 받아와서 데이터를 전송해 줄 수도 있다. no를 받아오면 해당하는 데이터들을 뿌려주게끔 소스코딩을 짰기 때문에 해당하는 내용을 가지고 와줄 것이다. 

$('.buttons').click(function(){
		let no=$(this).attr("value");
		$.ajax({
			type:'POST',
			url:'movie_list.do',
			data:{"no":no},
			success:function(result)
			{
				let json=JSON.parse(result);
				let res="";
				for(let i=0; i<json.length; i++)
				{
					res+="<tr>"
						+"<td>"
						+"<img src=https://www.kobis.or.kr/"+json[i].thumbUrl+" width=30 height=30></td>"
						+"<td>"+json[i].movieNm+"</td>"
						+"<td>"+json[i].director+"</td>"
						+"<td>"+json[i].genre+"</td>"
						+"<td>"+json[i].watchGradeNm+"</td>"
						+"</tr>"
				}
				$('#movie_list').html(res);
			}
		})
		
		
	})

뿌려주면 대충 이렇다

 

아직 파싱말고는 포스팅 하지도 못했는데 너무 길어지는거 같아서 새로운 글에 다시 블로깅하도록 하겠다

728x90
반응형