[Java] 네이버(Naver) 검색 사용 및 JSON 파싱(Parsing)하기

    네이버 API 등록을 하는 것은 바로 이전 포스팅을 참고하면 되며

    [Java] 네이버 검색 API 등록 및 호출하기

     

    [Java] 네이버 검색 API 등록 및 호출하기

    네이버 검색 API 등록 모든 API가 그러하지만 네이버 검색도 사용하기 위해서는 우선적으로 API 등록해서 키를 발급받아야 한다. developers.naver.com/docs/search/blog/ 검색 API 블로그 검색 개발가이드 NAVER

    needjarvis.tistory.com

    위 내용이 마무리 된 사람을 기준으로 네이버 검색 및 간단하게 파싱(Parsing)하는 법에 대해서 설명하고자 한다.

     

     

    NaverCrawlerMain.java

    import java.net.URLEncoder;
    import java.util.Map;
    
    
    /**
     * 네이버 크롤러 메인 클래스
     * 
     * @author steel
     * @since 2021.02.24
     */
    public class NaverCrawlerMain {
    
    	public static void main(String[] args) {
    		String id = "클라이언트아이디";
            String secret = "시크릿값";
            
            try {
    	        NaverCrawler crawler = new NaverCrawler();
    	        String url = URLEncoder.encode("needjarvis", "UTF-8");
    	        String response = crawler.search(id, secret, url);
    	        
    	        String[] fields = {"title", "link", "description"};
    	        Map<String, Object> result = crawler.getResult(response, fields);
    	        
    	        if(result.size() > 0) System.out.println("total -> " + result.get("total"));
    	        
    			List<Map<String, Object>> items = (List<Map<String, Object>>) result.get("result");
    	        for(Map<String, Object> item : items) {
    	        	System.out.println("====================================================");
    	        	for(String field : fields) System.out.println(field + "->" + item.get(field));	        	
    	        }
            } catch (Exception e) {
            	e.printStackTrace();
            }
    	}
    }
    

     

    위 코드는 블로그에서 needjarvis를 검색어로 호출을 해보았다. 사실 needjarvis는 영문이라 URLEncoder를 할 필요는 없지만 그래도 다른 한글 검색어를 넣을려면 encode는 필수적으로 해야 검색이 정상적으로 이루어지게 된다.

     

    search 메소드를 호출하여 네이버 검색 결과를 String 형태로 그대로 받아서 response라는 변수에 넣게 되는데 이 값을 기준으로 total과 검색 결과를 화면에 뿌리는 것이 본 포스팅의 목표이다.

     

     

    NaverCrawler.java

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.net.HttpURLConnection;
    import java.net.URL;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    import org.json.simple.JSONArray;
    import org.json.simple.JSONObject;
    import org.json.simple.parser.JSONParser;
    
    
    /**
     * 네이버 블로그 크롤링
     * 
     * @author steel
     * @since 2021.02.24
     */
    public class NaverCrawler {
    	// 베이스 URL
    	final String baseUrl = "https://openapi.naver.com/v1/search/blog.json?query=";
    	
    	public String search(String clientId, String secret, String _url) {
    		HttpURLConnection con = null;
    		String result = "";
            
            try {
                URL url = new URL(baseUrl + _url);
                con = (HttpURLConnection) url.openConnection();
    
                con.setRequestMethod("GET");
                con.setRequestProperty("X-Naver-Client-Id", clientId);
                con.setRequestProperty("X-Naver-Client-Secret", secret);
    
                int responseCode = con.getResponseCode();
                if (responseCode == HttpURLConnection.HTTP_OK) result = readBody(con.getInputStream());
                else result = readBody(con.getErrorStream());
    
            } catch (Exception e) {
                System.out.println("연결 오류 : " + e);
            } finally {
                con.disconnect();
            }
    
            return result;
    	}
    	
    	
    	/**
    	 * 결과를 읽는다
    	 * 
    	 * @param body
    	 * @return
    	 */
    	public String readBody(InputStream body){
    		InputStreamReader streamReader = new InputStreamReader(body);
    
    		try (BufferedReader lineReader = new BufferedReader(streamReader)) {
                StringBuilder responseBody = new StringBuilder();
    
                String line;
                while ((line = lineReader.readLine()) != null) {
                    responseBody.append(line);
                }
    
                return responseBody.toString();
            } catch (IOException e) {
                throw new RuntimeException("API 응답을 읽는데 실패했습니다.", e);
            }
        }
    	
    	
    	/**
    	 * 결과를 파싱하는 메소드
    	 * 
    	 * @param response
    	 * @param fiels
    	 * 
    	 * @return
    	 */
    	public Map<String, Object> getResult(String response, String[] fields) {
    		Map<String, Object> rtnObj = new HashMap<> ();
    		
    		try {
    			JSONParser parser = new JSONParser();
    			JSONObject result = (JSONObject) parser.parse(response);
    			
    			rtnObj.put("total", (long) result.get("total"));
    			
    			JSONArray items = (JSONArray) result.get("items");
    			List<Map<String, Object>> itemList = new ArrayList<> ();
    			
    			for(int i = 0; i < items.size(); i++) {
    				JSONObject item = (JSONObject) items.get(i);
    				Map<String, Object> itemMap = new HashMap<> ();
    				
    				for(String field : fields) {
    					itemMap.put(field, item.get(field));
    				}
    				itemList.add(itemMap);
    			}
    			
    			rtnObj.put("result", itemList);
    		} catch (Exception e) {
    			System.out.println("getResult error -> " + "파싱 실패, " + e.getMessage());			
    		}
    		
    		return rtnObj;
    	}
    }
    

     

    위 메소드는 각각 search는 검색어를 HttpUrlConnection으로 네이버 API에 요청하여 결과를 가져오는데 이때 stream 형태로 되어 있어서 stream을 string으로 변환하는 메소드를 호출한다. 

     

    순수하게 string형태의 response를 가지고 getResult를 호출하여 결과를 파싱하게 되어 있는데 현재 위에 예제는 total값만 파싱하게 만들었다. 위 예제를 구현하기 위해서는 자바 기본 라이브러리(Library)로 가능한 것이 아니라 json을 파싱하기 위한 라이브러리를 새로 추가해야 한다.

     

    mvnrepository.com/artifact/com.googlecode.json-simple/json-simple/1.1.1

     

    Maven Repository: com.googlecode.json-simple » json-simple » 1.1.1

    A simple Java toolkit for JSON com.googlecode.json-simple json-simple 1.1.1 // https://mvnrepository.com/artifact/com.googlecode.json-simple/json-simple implementation group: 'com.googlecode.json-simple', name: 'json-simple', version: '1.1.1' // https://mv

    mvnrepository.com

    본 포스팅에서 사용한 Json 파서(Parser) 라이브러리는 json-simple 라이브러리로 1.1.1 버전을 사용하였다. 위 메이븐 경로에서 받을수도 있고 아래의 링크한 jar파일을 클릭하여 직접 다운로드 받아도 상관 없다.

     

    json-simple-1.1.1.jar
    0.02MB

     

    해당 라이브러리를 등록하면, json-simple을 사용할 수 있는데 제일 먼저 string 형태의 값을 parse 메소드를 호출하여 jsonObject로 변형 후 그 다음 결과값에 따라서 파싱을 해주면 된다.

     

    파싱을 할 때 딱 2개만 알면 된다. 현재 결과가 Key, Value 형태로 되어 있으면, JSONObject 현재 결과가 Array 혹은 List 형태로 되어 있으면(복수형) JSONArray를 선언한다.

     

    네이버 결과 구조

    Response의 결과를 보면 크게 2가지의 형태로 되어 있는데 하나는 전체 결과의 상황을 알려주는 데이터와 검색값을 알려주는 데이터로 구분된다. 

    우선 결과 상황을 알려주는 데이터는 다음과 같다

    {"lastBuildDate": "Wed, 24 Feb 2021 10:30:24 +0900","total": 106,"start": 1,"display": 100}

    위 데이터는 JSON에서 최상위 위치(depth)에 있기 때문에 Map에서 키를 호출하듯 사용하면 된다. lastBuildData, total, start, display 모두 최상위 위치라서 위 코드를 보면 그냥 result.get("total")로 값을 가져오게 되는 것이다.

     

     

    그리고 다음 Depth 형태로 item 결과들이 있다. 하지만 여기서 알아야 될 것은 item 자체는 최상위에 있다는 점이다.

    "items": [{"title": "빅데이터 분석 주제 유형","link": "https:\/\/blog.naver.com\/sky00141?Redirect=Log&logNo=222218730000","description": "빅데이터 분석 주제의 4가지 유형 - 이미지 출처 :https://<b>needjarvis</b>.tistory.com/505 최적화 (Optimization)은 분석 대상과 분석 방법을 모두 알고 있는 경우 문제를 해결하기 위해 수행하는 방법이며, 솔루션... ","bloggername": "제이의 IT Security 블로그","bloggerlink": "https://blog.naver.com/sky00141","postdate": "20210125"}....

    위 item의 결과를 자바의 형으로 이해하면 다음과 같다.

    Map<String, List<String, String>> items

    즉 items라는 녀석은 Map형태처럼 되어 있지만 내부 결과는 리스트로 되어 있고, 데이터 형태는 String으로 이루어진 Key, Value 구조의 맵이다. 

     

    rtnObj.put("total", (long) result.get("total"));
    JSONArray items = (JSONArray) result.get("items");

    그래서 NaverCrawler.java에서 total과 item의 값을 처리하는 방식이 다르다. total의 경우 간단하게 map에서 get을 하듯 가져오지만 items의 경우 value를 JSONArray로 다시 형변환을 하며, for문을 돌려서 items의 결과를 처리한다. 

     

    최종결과

    total -> 105
    ====================================================
    title->빅데이터 분석 주제 유형
    link->https://blog.naver.com/sky00141?Redirect=Log&logNo=222218730000
    description->빅데이터 분석 주제의 4가지 유형 - 이미지 출처:https://<b>needjarvis</b>.tistory.com/505 최적화(Optimization)은 분석 대상과 분석 방법을 모두 알고 있는 경우 문제를 해결하기 위해 수행하는 방법이며, 솔루션...
    ====================================================
    title->엘라스틱서치(Elasticsearch) 노드(Node)의 종류
    link->https://blog.naver.com/koys007?Redirect=Log&logNo=222246765077
    description->yml 에서 아래 내용 추가 node.master: false node.data: false node.ingest: true search.remote.connect: false 출처: https://<b>needjarvis</b>.tistory.com/579 [자비스가 필요해] ====================================================
    title->척도(Metrics)
    link->https://blog.naver.com/jamsuham75?Redirect=Log&logNo=222216354329
    description->둘간의 개념이 사실상 유사하기 때문에 동일한 개념으로 어쩔 땐 척도를 사용하기도 하고 어쩔 땐 손실함수를 쓰기도 한다. 출처 : https://<b>needjarvis</b>.tistory.com/568 ====================================================
    title->Mysql 페이징
    link->https://blog.naver.com/vivacarla?Redirect=Log&logNo=222134289375
    description->page=1로 셋팅함 srchDetail.offSet = (srchDetail.page - 1) * srchDetail.detailViewSize 이므로 detailViewSize 는 이런거 말함 https://<b>needjarvis</b>.tistory.com/259
    ....

     

    연관포스팅

    [Java] 네이버 검색 API 등록 및 호출하기

    댓글

    Designed by JB FACTORY