JAVA

스트링부트 웹 크롤링 하는 방법[jsoup]

스트링부트 웹 크롤링 하는 방법[Jsoup]

Jsoup 사용하는 방법

Jsoup는 자바 언어로 HTML을 쉽게 파싱할 수 있게 도와주는 라이브러리이다.

1.Maven 저장소에서 Jsoup 코드를 복사해서 pom.xml 파일에 붙여넣기 한다.
	<dependencies>

		<!-- 추가한 라이브러리 시작 -->
		<!-- https://mvnrepository.com/artifact/org.jsoup/jsoup -->
		<dependency>
			<groupId>org.jsoup</groupId>
			<artifactId>jsoup</artifactId>
			<version>1.13.1</version>
		</dependency>
		<!-- 추가한 라이브러리 끝 -->
		<!-- 중략 -->

	</dependencies>
spring
의존성 관리 도구 Maven 저장소 활용하는 방법Maven이란 공통 레퍼지토리로 보통 라이브러리가 서로 연관성이 있는 경우, 연관되어 있는 라이브러리를 모두 다운 받아야하는데, 이 저장소를 활용하면 상위 라이브러리만 가져오면 하위 라이브러리도 자동으로 가져오게 된다....
Jsoup 라이브러리가 먹히지 않을 경우 STS를 다시 시작해 보세요.
2.url에서 HTML 문서 가져온다.
Document doc = Jsoup.connect(url).get();

 

3.HTML에서 원하는 요소를 가져온다.
Elements elem = doc.select("#articleTitle");

 

네이버 뉴스 기사 웹 크롤링하기

HTTP 서버와 통신하는 방법

RestTemplate는 spring 3.0부터 지원하는 HTTP 서버와 통신하는 방법 중 하나로 기계적이고 반복적인 코드를 최대한 줄여주며 json, xml 응답에 적합하다. 그 외에도 HTTP 서버와 통신하는 방법으로 자바에서는 HttpUrlConnection, okHttp, RestTemplate, Retrofit2 등을 사용할 수 있다. (파이썬에서는 requests 사용).

Jsoup만 사용해서 통신을 할 수 있으나 여기서는 RestTemplate 사용법을 익히고자 두 가지 방법을 모두 사용한 방법을 소개한다.

네이버 뉴스 기사 HTML 분석하기

정치 카테고리에 있는 뉴스 기사 제목과 기사 발행일을 크롤링하려고 합니다. 여기서 뉴스 기사 제목과 기사 발행일을 추출하기 위한 id/class 값을 분석합니다. 뉴스 기사 제목은 유일한 값인 id값 ‘articleTitle’을 사용하면 되고, 기사 발행일은 class값으로  ‘.t11’이 주어져 있는데 다른 곳에서 사용하고 있는지 document.querySelect()를 사용해서 확인해 봅니다. 여기서는 ‘.t11’가 두 군데 사용되고 있어서 [0]번째를 사용하기로 합니다.

crawling

크롤링 정보를 한번에 담을 객체 생성

package com.cos.newssave.batch;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;

@Builder
@AllArgsConstructor
@Data
public class NewsTest {
  
  private String title;
  private String time;
  
}

 

RestTemplate 사용

package com.cos.newssave.batch;

import java.util.ArrayList;
import java.util.List;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.junit.jupiter.api.Test;
import org.springframework.web.client.RestTemplate;

public class NaverCrawTest {

  int aidNum = 1;

  @Test
  public void test3() {

    RestTemplate rt = new RestTemplate(); //RestTemplate 객체 생성
    List<NewsTest> nts = new ArrayList<>(); //수집한 collections를 담기 위한 리스트
    
    for(int i = 1; i < 11; i++) {
      String aid = String.format("%010d", aidNum); //10자리 숫자를 만들기 위한 문자열 포맷
      String url = "https://news.naver.com/main/read.naver?mode=LSD&mid=shm&sid1=100&oid=003&aid="+aid; //사용할 네이버 뉴스 기사 주소
      String html = rt.getForObject(url, String.class);//해당 주소에서 html을 담아준다.
      
      Document doc = Jsoup.parse(html);//html 문서를 Jsoup 도큐먼트에 담아준다.

      Element titleElement = doc.selectFirst("#articleTitle"); //뉴스 기사 제목 요소를 가지고 온다.
      Element timeElement = doc.selectFirst(".t11"); //기사 발행일 요소를 가지고 온다.
      String title = titleElement.text(); //html 태그를 제거하고 텍스트만 가지고 온다.
      String time = timeElement.text(); 
      
      System.out.println(title);
      System.out.println(time);
      
      NewsTest nt = NewsTest.builder() //크롤링 정보를 담아줄 객체를 만든다.
        .title(title)
        .time(time)
        .build();
      
      nts.add(nt); //리스트에 객체를 더해준다.
      
      aidNum++; //반복문을 돌 때마다 기사 아이디를 더해준다.
    }

    //System.out.println(nts.size());
    //assertTrue(nts.size() == 11); JUnit으로 테스트 통과하는지 알 수 있다. 

  }

}
<결과 화면>
result

RestTemplate 미사용

package com.cos.newssave.batch;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.junit.jupiter.api.Test;
import org.springframework.web.client.RestTemplate;

public class NaverCrawTest {

  int aidNum = 1;

  @Test
  public void test4() {

    RestTemplate rt = new RestTemplate();
    List<NewsTest> nts = new ArrayList<>(); // collections

    for (int i = 1; i < 11; i++) {
      String aid = String.format("%010d", aidNum);
      String url = "https://news.naver.com/main/read.naver?mode=LSD&mid=shm&sid1=100&oid=003&aid=" + aid;

      try {
        Document doc = Jsoup.connect(url).get();
        Element titleElement = doc.selectFirst("#articleTitle");
        Element timeElement = doc.selectFirst(".t11");

        String title = titleElement.text();
        String time = timeElement.text();

        System.out.println(title);
        System.out.println(time);

        NewsTest nt = NewsTest.builder().title(title).time(time).build();
        nts.add(nt);

        aidNum++;
      } catch (IOException e) {
        e.printStackTrace();
      }


    }
    System.out.println(nts.size());

  }

}
<결과 화면>
result
최신글