목차
다음글
Jsoup이란?
jsoup은 Dom메서드와 CSS Selector를 사용하여 HTML의 데이터를 추출할 수 있는 Java 라이브러리이다.
크롤링해보기
크롤링할 URL 준비, Dom Selector 찾기
나는 단어장 앱을 만들려고한다. 단어에 해당하는 문장을 표시해주고, 단어를 맞추면 된다.
이 단어들이 포함된 문장들을 크롤링하고자한다.
크롬 개발자도구로 열어보면 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&tag=monokaki0f-22&linkCode=ur2&camp=247&creative=1211&index=books&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&l=ur2&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을 사용해야한다.
'Backend' 카테고리의 다른 글
Spring Container(ApplicationContext)와 Bean (0) | 2022.03.28 |
---|---|
자바, Spring Boot로 크롤링하기 - Selenium 이용 (동적페이지), 속도 개선 방법 (0) | 2022.03.08 |
[Spring Security] OAuth 카카오 로그인하기 (0) | 2022.02.23 |
[JPA] 값 타입(기본값, @Embedded, 값타입 컬렉션) (0) | 2022.02.22 |
[JPA] 프록시와 즉시로딩, 지연로딩 / 영속성 전이와 고아객체 (0) | 2022.02.21 |