본문 바로가기
프로그래밍 언어/JAVA

자바기반 웹 크롤링(jsoup)

by zieunee 2019. 8. 2.
반응형

jsoup를 사용하여 자바 웹 크롤링을 해보았다.

 

이 사진의 url에서 (http://rank.ezme.net/diff) 의 다음,네이버,구글의 실시간 검색어를 모두 크롤링하여 중복을 제거하는 것을 수행하였다.

 

문제

  1. 시간대별로 (12시, 13시, 10시 등등 ) 원하는 시간을 선택하여 검색어 추출 ==> textfield 만들어서 입력값 함수 생성

  2. 검색어 중복을 제거(구글,네이버에 같은 검색어가 있으면 1개만 추출) ==> set 사용

  3. 여러시간을 선택할 때 원하는시간말고 선택한 다른시간의 검색어는 중복제거. (10,9,8 이라면 10이 원하는 시간 9,8시가 중복 제거해야할 시간 // 10시에 ''안녕'' , ''뭐해'', ''그래'' 가있고 9시에 ''안녕'' 8시에 ''뭐해''가 있다면 ''그래''만 출력해야한다.) ==> removeAll 함수 생성으로 중복 제거

 

처음에 jsoup라이브러리 없이 buffer로 사용했다가 ,, 안될것 같아서 jsoup라이브러리를 사용했다

.

jsoup.jar를 사이트에서 다운

properties > Java Build Path > Libraries > Add External JARs 로 jar 파일을 추가

 

추가 후 import 해서 사용

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

 

처음에 url을 불러와 html 을 크롤링 하는 코드

 ArrayList<String> result = new ArrayList<String>();    //결과를 넣을 리스트  
 String inputValue = t; //입력받을 원하는 시간

 //get html
 String url = "http://rank.ezme.net/diff"; 
 Document doc = Jsoup.connect(url).userAgent("Mozilla").get();
 Elements elems = doc.select(".mdl-data-table"); // .mdl-data-table이 들어간 html 을 가져옴 
 Element elemtbody = elems.select("tbody").get(0);
 int curTime = Integer.parseInt((elemtbody.select("tr.bg_info").first()).select("td").first().text().replace("시", ""));//가장 최근 시간

".mdl-data-table" 테이블을 가리키는 DATA

 

"tbody"를 가리키는 DATA

원하는 시간 값 체크

     //get input value
       List<Integer> list = queryString(curTime, inputValue); // 현재시간, 원한느 시간값 넣음
       .....


          //input value 처리 function
    public static List<Integer> queryString(int curTime, String inputValue){

        List<Integer> list = new ArrayList<Integer>();

        if(inputValue == null || inputValue == ""){
            return list;
        } //inputValue값이 없으면 리턴

        String[] sql = inputValue.split(" "); // 띄어쓰기 기준으로 split

        for(int i=0; i< sql.length; i++){
            if(curTime < Integer.parseInt(sql[i])){ //현재시간보다 큰값이면 수행x
                continue;
            }else{
                list.add(Integer.parseInt(sql[i])); // 리스트에 원하는 시간 값 넣음 
            }
        }

        return list;
    }

 

문제 3번작업 설정 , 중복제거(set이용)

     //parseHTML
       Set<String> realTimeSet = new HashSet<String>(); //중복제거를 위한 set
       for(int i=0;i<list.size();i++){ 
           if(i==0) { //맨 처음 값 기준 (원하는 값)
               realTimeSet= parseHTML(curTime, list.get(i), elemtbody, realTimeSet);
               System.out.println("parseHTML : " + realTimeSet.size() + ", " + realTimeSet.toString());
           }else { // 나머지 중복 제거할 값 
               realTimeSet= removeAll(curTime, list.get(i), elemtbody, realTimeSet);
               System.out.println("removeAll : " + realTimeSet.size() + ", " + realTimeSet.toString());
           }
       }

......


   //웹 크롤링 function 더하기 
    public static Set<String> parseHTML(int curTime, int inputTime, Element elemtbody, Set<String> realTimeSet){
        Element elemtr = null;

        int timetable = (curTime - inputTime) * 10 ; // 전체 행이 10개이기 때문 11시에서 12시 사이는 10개에 해당 
       int j = 0;
       for(int i=0 ; i<10 ; i++){ //현재 13시고 12시것을 가져오고 싶다면 10번째부터 20번째까지 값 가져오면 됨
           j = i+timetable;
           elemtr = elemtbody.select("tr").get(j); //tbody에 해당하는 tr 값의 j번째 값을 가져옴 
           if(j % 10 == 0){ //첫번째 줄은 'o시'가 있기 때문에 'o시,순위,1,2,3' 으로 이뤄져있다. 
               System.out.println(">> "+ elemtr.select("td").get(0).text());

               realTimeSet.add(elemtr.select("td").get(2).text());
               realTimeSet.add(elemtr.select("td").get(3).text());
               realTimeSet.add(elemtr.select("td").get(4).text());

           }else{ // 나머지는 '순위/ 검색어 1,2,3' 으로 이뤄져있음 
                realTimeSet.add(elemtr.select("td").get(1).text());
                realTimeSet.add(elemtr.select("td").get(2).text());
                realTimeSet.add(elemtr.select("td").get(3).text());
           }
       }

        return realTimeSet;
    }


    //웹 크롤링 function 다른시간과 겹치는값 지우기
    public static Set<String> removeAll(int curTime, int inputTime, Element elemtbody, Set<String> realTimeSet){
        Element elemtr = null;


        int timetable = (curTime - inputTime) * 10 ;
        int j = 0;
        for(int i=0 ; i<10 ; i++){
            j = i+timetable;
            elemtr = elemtbody.select("tr").get(j);
            if(j % 10 == 0){
                System.out.println(">> " +elemtr.select("td").get(0).text());

                realTimeSet.remove(elemtr.select("td").get(2).text());
                realTimeSet.remove(elemtr.select("td").get(3).text());
                realTimeSet.remove(elemtr.select("td").get(4).text());

            }else{
                realTimeSet.remove(elemtr.select("td").get(1).text());
                realTimeSet.remove(elemtr.select("td").get(2).text());
                realTimeSet.remove(elemtr.select("td").get(3).text());
            }
        }

        return realTimeSet;
    }

첫째 행은 4개/ 나머지 행은 3개 ,, 총 10개의 행

 

완성된 소스 최종

package com.glab.app.service;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

public class ParsingService {

    /**
     * 검색어를 파싱
     * @param args
     * @throws Exception
     */
    public ArrayList<String> parsingKeyword(String t) throws Exception {
        System.out.println("@@keyword reading start.@@  >> ");
        ArrayList<String> result = new ArrayList<String>();    
        String inputValue = t;

        //get html
        String url = "http://rank.ezme.net/diff";
        Document doc = Jsoup.connect(url).userAgent("Mozilla").get();
       Elements elems = doc.select(".mdl-data-table");
       Element elemtbody = elems.select("tbody").get(0);
       int curTime = Integer.parseInt((elemtbody.select("tr.bg_info").first()).select("td").first().text().replace("시", ""));//가장 최근 시간


       //get input value
       List<Integer> list = queryString(curTime, inputValue);


       //parseHTML
       Set<String> realTimeSet = new HashSet<String>();
       for(int i=0;i<list.size();i++){
           if(i==0) {
               realTimeSet= parseHTML(curTime, list.get(i), elemtbody, realTimeSet);
               System.out.println("parseHTML : " + realTimeSet.size() + ", " + realTimeSet.toString());
           }else {
               realTimeSet= removeAll(curTime, list.get(i), elemtbody, realTimeSet);
               System.out.println("removeAll : " + realTimeSet.size() + ", " + realTimeSet.toString());
           }
       }


       Iterator<String> iterator = realTimeSet.iterator();
       for(int i=0;i<realTimeSet.size();i++) {
            result.add(iterator.next());
        }

    //   result= realTimeSet;
        return result;

    }



    //input value 처리 function
    public static List<Integer> queryString(int curTime, String inputValue){

        List<Integer> list = new ArrayList<Integer>();

        if(inputValue == null || inputValue == ""){
            return list;
        }


        String[] sql = inputValue.split(" ");

        for(int i=0; i< sql.length; i++){
            if(curTime < Integer.parseInt(sql[i])){
                continue;
            }else{
                list.add(Integer.parseInt(sql[i]));
            }
        }

        return list;
    }

    //웹 크롤링 function
    public static Set<String> parseHTML(int curTime, int inputTime, Element elemtbody, Set<String> realTimeSet){
        Element elemtr = null;


        int timetable = (curTime - inputTime) * 10 ;
       int j = 0;
       for(int i=0 ; i<10 ; i++){
           j = i+timetable;
           elemtr = elemtbody.select("tr").get(j);
           if(j % 10 == 0){
               System.out.println(">> "+ elemtr.select("td").get(0).text());

               realTimeSet.add(elemtr.select("td").get(2).text());
               realTimeSet.add(elemtr.select("td").get(3).text());
               realTimeSet.add(elemtr.select("td").get(4).text());

           }else{

                realTimeSet.add(elemtr.select("td").get(1).text());
                realTimeSet.add(elemtr.select("td").get(2).text());
                realTimeSet.add(elemtr.select("td").get(3).text());
           }
       }

        return realTimeSet;
    }


    //웹 크롤링 function
    public static Set<String> removeAll(int curTime, int inputTime, Element elemtbody, Set<String> realTimeSet){
        Element elemtr = null;


        int timetable = (curTime - inputTime) * 10 ;
        int j = 0;
        for(int i=0 ; i<10 ; i++){
            j = i+timetable;
            elemtr = elemtbody.select("tr").get(j);
            if(j % 10 == 0){
                System.out.println(">> " +elemtr.select("td").get(0).text());

                realTimeSet.remove(elemtr.select("td").get(2).text());
                realTimeSet.remove(elemtr.select("td").get(3).text());
                realTimeSet.remove(elemtr.select("td").get(4).text());

            }else{
                realTimeSet.remove(elemtr.select("td").get(1).text());
                realTimeSet.remove(elemtr.select("td").get(2).text());
                realTimeSet.remove(elemtr.select("td").get(3).text());
            }
        }

        return realTimeSet;
    }

}

 

 

10, 9, 8시 입력시 10기준으로 9시8시것 중복제거 된 채로 나오게 된다. 

 

반응형

'프로그래밍 언어 > JAVA' 카테고리의 다른 글

가비지컬렉션  (0) 2020.12.04
12. 입출력 작업하기  (0) 2019.02.12
11. 예외 처리하기  (0) 2019.02.12
10. 컬렉션 API활용하기  (0) 2019.02.12
09. 기본 API활용하기  (0) 2019.02.11