Backend

자바, Spring Boot로 크롤링하기 - Jsoup 이용 (정적페이지)

연_우리 2022. 3. 7. 22:46
반응형

목차

     

     

    다음글

     

    자바, Spring Boot로 크롤링하기 - Selenium 이용 (동적페이지), 속도 개선 방법

    목차 이전글 자바, Spring Boot로 크롤링하기 - Jsoup 이용 (정적페이지) 목차 Jsoup이란? jsoup은 Dom메서드와 CSS Selector를 사용하여 HTML의 데이터를 추출할 수 있는 Java 라이브러리이다. 크롤링해보기 크

    lotuus.tistory.com

     

     

     

    Jsoup이란?

    jsoup은 Dom메서드와 CSS Selector를 사용하여 HTML의 데이터를 추출할 수 있는 Java 라이브러리이다.

     

     

     

     

     

    크롤링해보기

    크롤링할 URL 준비, Dom Selector 찾기

    나는 단어장 앱을 만들려고한다. 단어에 해당하는 문장을 표시해주고, 단어를 맞추면 된다.

    이 단어들이 포함된 문장들을 크롤링하고자한다.

     

    https://yourei.jp/腕を磨く 

    크롬 개발자도구로 열어보면 id="sentence-N"의 파란부분에서 문장을 가져올 수 있다.

     

     

     

     

    SpringBoot build.gradle에 의존성 추가

    https://mvnrepository.com/artifact/org.jsoup/jsoup 참고

    implementation 'org.jsoup:jsoup:1.14.2'

     

     

     

    크롤링 코드

    import org.jsoup.Connection;
    import org.jsoup.Jsoup;
    import org.jsoup.nodes.Document;
    import org.jsoup.nodes.Element;
    import org.jsoup.select.Elements;
    import org.springframework.stereotype.Component;
    
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.List;
    
    
    public class CrawlingExample {
    
        /**
         * 조회할 URL셋팅 및 Document 객체 로드하기
         */
        private static final String url = "https://yourei.jp/腕を磨く";
        public void process() {
            Connection conn = Jsoup.connect(url);
            //Jsoup 커넥션 생성
    
            Document document = null;
            try {
                document = conn.get();
                //url의 내용을 HTML Document 객체로 가져온다.
                //https://jsoup.org/apidocs/org/jsoup/nodes/Document.html 참고
            } catch (IOException e) {
                e.printStackTrace();
            }
    
            List<String> list = getDataList(document);
        }
    
    
        /**
         * data가져오기
         */
        private List<String> getDataList(Document document) {
            List<String> list = new ArrayList<>();
            Elements selects = document.select(".sentence-list");	//⭐⭐⭐
            //select 메서드 안에 css selector를 작성하여 Elements를 가져올 수 있다.
    
            for (Element select : selects) {
                System.out.println(select.html());		//⭐⭐⭐
                //html(), text(), children(), append().... 등 다양한 메서드 사용 가능
                //https://jsoup.org/apidocs/org/jsoup/nodes/Element.html 참고
            }
            return list;
        }
    
    }

    메서드 참고

    https://jsoup.org/apidocs/org/jsoup/nodes/Document.html

    https://jsoup.org/apidocs/org/jsoup/nodes/Element.html

     

    Jsoup의 사용방법은 정말 간단하다.

    Connection conn = Jsoup.connect(크롤링할 url); jsoup 커넥션 생성
    Document document = conn.get();  url의 내용 HTML의 Document 객체를 가져온다
    Elements selects = document.select(css selector);  select로 Document 객체의 Elements를 가져온다
    Element select = selects.get(0); Element를 가져온다

    이렇게 가져온 데이터를 입맛대로 조작하면된다.

     

     

     

    일단 select.html()의 결과는 아래와 같다.

    <li id="sentence-1" class="with-source-title list-group-item sentence odd clickable-sentence"> 
        <span class="prev-sentence" style="display:none;">そしてともに迷宮を探索するうち、知らず俺は自分とガッシュを比べ始めていた。</span>
        ⭐<span class="the-sentence">この先腕を磨いていけば、いつかはこの男に勝てる日がくるのだろうか。</span>
        <span class="next-sentence" style="display:none;">別段劣等感に苛まれていたわけでもなかった。</span> 
        <span class="next-sentence-preview">...</span> 
     	<div class="sentence-source-title">
            <a target="_blank" href="https://www.amazon.co.jp/gp/search?ie=UTF8&amp;tag=monokaki0f-22&amp;linkCode=ur2&amp;camp=247&amp;creative=1211&amp;index=books&amp;keywords=%E3%83%99%E3%83%8B%E3%83%BC%E6%9D%BE%E5%B1%B1%20%E9%A2%A8%E3%82%88%20%E9%BE%8D%E3%81%AB%E5%B1%8A%E3%81%84%E3%81%A6%E3%81%84%E3%82%8B%E3%81%8B%20%E4%B8%8B%20">ベニー松山『風よ。龍に届いているか(下)』</a>
            <img src="//ir-jp.amazon-adsystem.com/e/ir?t=monokaki0f-22&amp;l=ur2&amp;o=9" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;">
        </div> 
    </li> 
    
    .....
    
    <li id="sentence-3" class="without-source-title list-group-item sentence odd nonclickable-sentence"> 
        <span class="the-sentence">地元のレースへ参加しその腕を磨き、のカート選手権では優勝を果たす。</span> 
    </li>

    크롬의 개발자도구로 보던 코드와는 다르다

    없었던 <span class="the-sentence"> 이 존재하고

    있었던 <span class="highlight"> 가 사라져있다.

     

     

     

    그냥 document를 출력해보자

    /**
     * data가져오기
     */
    private List<String> getDataList(Document document) {
        System.out.println(document);
        return null;
    }
    .....
    <script>
        var HIGHLIGHT_NGRAM_RE = new RegExp("((<ruby>)?\u8155(<rt>.+?</rt>)*?(</?ruby>)*?\u3092(<rt>.+?</rt>)*?(</?ruby>)*?\u78e8(<rt>.+?</rt>)*?(</?ruby>)*?\u304f(<rt>.+?</rt>)?(</ruby>)?|(<ruby>)?\u8155(<rt>.+?</rt>)*?(</?ruby>)*?\u3092(<rt>.+?</rt>)*?(</?ruby>)*?\u78e8(<rt>.+?</rt>)*?(</?ruby>)*?\u3044(<rt>.+?</rt>)?(</ruby>)?|(<ruby>)?\u8155(<rt>.+?</rt>)*?(</?ruby>)*?\u3092(<rt>.+?</rt>)*?(</?ruby>)*?\u78e8(<rt>.+?</rt>)*?(</?ruby>)*?\u304d(<rt>.+?</rt>)?(</ruby>)?|(<ruby>)?\u8155(<rt>.+?</rt>)*?(</?ruby>)*?\u3092(<rt>.+?</rt>)*?(</?ruby>)*?\u78e8(<rt>.+?</rt>)*?(</?ruby>)*?\u304b(<rt>.+?</rt>)?(</ruby>)?)", 'i');
        $('ul.sentence-list span.the-sentence, li#ngram-abstract').replaceWith(function() {
          return $(this).html().replace(HIGHLIGHT_NGRAM_RE, '<span class="highlight">$1</span>');
        });
    </script>
    .....

    출력해본 하단에 위와 같은 script 코드가 있었다.

    즉, 위에서 select.html()로 가져온 코드는 script가 적용되기 이전의 코드인 것을 알 수 있다.

     

     

     

    Jsoup은 정적 페이지를 파싱할 수 있다.

    Jsoup은 Http Request를 사용하는 라이브러리여서 정적 페이지만 파싱할 수 있다!!!

    위에처럼 자바스크립트까지 적용 완료된 동적 페이지를 파싱하려면 Selenium을 사용해야한다.

     

     

    반응형
    • 네이버 블러그 공유하기
    • 페이스북 공유하기
    • 트위터 공유하기
    • 구글 플러스 공유하기
    • 카카오톡 공유하기