Java - Jsoup API

강서진·2023년 11월 20일
1

Java

목록 보기
27/35
post-thumbnail
post-custom-banner

강좌 Course 2. Part 3. ch1 3강 요약

Jsoup

이번에 사용해 볼 api 이름이 Jsoup인 것을 보니, 파이썬에서 사용했던 BeautifulSoup이 생각났다. 웹 크롤링 / 스크래핑에 사용되는 api겠거니 예상하고 강의를 들었다.

Jsoup은 html문서를 읽고 파싱하여 웹 크롤링, 웹 스크래핑, 데이터 추출 등의 작업을 수행하는 자바 라이브러리이다. 공식문서

1.15.3 버전을 받았다. 역시 project structure에 추가해준 후 사용할 수 있다.
강의에서는 성경 말씀 사이트를 크롤링하였지만, 나는 가사 모음 사이트에서 좋아하는 노래 가사를 크롤링하는 것으로 하였다.

뮤비
html을 슥 보니 가사는 전부 lyrics container에 담겨있는 것 같아 이 태그를 눈여겨보았다.

Jsoup을 사용하여 html을 파싱하려면 우선 url을 connect에 인수로 넘겨 response를 받아와야 한다. url이 잘못되었을 때를 대비하여 IOException을 받을 수 있도록 try-catch 문을 사용하였다.
추출해낼 정보는 노래 제목, 앨범, 가수, 그리고 가사로 정하였다. 노래 정보도 여러 개고, 가사도 3개의 div에 나뉘어 있어서 전부 Elements로 받았다.

public class JsoupExample {
    public static void main(String[] args) {
        String url = "https://genius.com/Hippo-campus-ride-or-die-lyrics";

        // Document from jsoup
        // in case url is wrong, catch exception (IOException)
        try {
            Document document = Jsoup.connect(url).userAgent("Mozilla").get();


            // SongDetails - title, artist, album
            Elements songDetails = document.getElementsByClass("SongHeaderdesktop__SongDetails-sc-1effuo1-5 dhqXbj");

            // lyrics-container - 3 paragraphs
            Elements songLyrics = document.getElementsByClass("Lyrics__Container-sc-1ynbvzw-1 kUgSbL");

            System.out.println(songDetails.text());
            System.out.println(songLyrics.text());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

하지만 다 쓰고 돌렸더니 403 에러가 돌아왔다...!
링크가 잘못되었는지 다시 확인해봤더니 문제는 없었다. 그래서 구글에 검색해보았더니 매크로를 막기 위해 UserAgent가 없는 request를 막아놓은 것이라 한다. 스택오버플로우 링크. 임시방편으로 connect()에

.userAgent("Mozilla")

를 추가하였더니 다행히도 에러가 뜨지 않고 잘 실행되었다.
하지만 여러번 요청을 보내면 또 문제가 생길 수도 있을 것 같다. 말했듯이 임시방편이기 때문에...

.text()를 제거하면 태그가 그대로 있는 것을 확인할 수 있다. 가사를 보기 좋게 태그를 제거하고 줄바꿈도 넣었다.

for (Element lyric : songLyrics){
                String l = lyric.toString();
                l = l.replaceAll("<div data-lyrics-container=\"true\" class=\"Lyrics__Container-sc-1ynbvzw-1 kUgSbL\">","");
                l = l.replaceAll("</div","");
                l = l.replaceAll("<br>","\n");
                System.out.println(l);
            }

stream으로 바꿔서 해야하나 했는데 String에 replace가 있어서 그냥 Jsoup Element를 문자열로 바꾸고 div 태그, 줄바꿈 태그를 수정하였다.

셀프 리뷰:

Lyrics Container같은 div 뒤에 붙은 노래 id들은 정규표현식으로 쓰면 훨씬 더 재사용성이 높아질 것 같다. 아니면 css 태그를 사용하든지 더 깔끔하게 원하는 정보를 뽑아내는 방법이 있을지도...
몇가지를 인터페이스로 만들어서 메서드로 정리하고 다듬으면, 지금처럼 곡 제목을 하드코딩해서 넣지 않아도 직접 가사를 뽑아줄 수 있을까 생각이 들었다.

post-custom-banner

0개의 댓글