[Java] Jsoup 이용한 CGV 영화 상영시간 크롤링

Jinny·2021년 12월 13일
1

JAVA

목록 보기
8/8
post-thumbnail

웹 크롤링

웹 크롤링이란 웹 사이트들에서 원하는 정보를 추출하는 것. 정식 명칭은 Scrapping이다.

  • 크롤링하는 것은 불법이 아니지만, 크롤링한 데이터를 배포해 서비스로 이용하는 것은 불법이 된다!

자바 웹 크롤링 라이브러리

Jsoup

HTML을 파싱해주는 Java 오픈소스 라이브러리이다.

정적인 자료를 수집하는 경우에 주로 사용한다.

정적 데이터를 비교적 빠르게 수집할 수 있지만 브라우저가 아닌 HTTP Request를 사용하기 때문에 동적 데이터를 수집하기 위해서는 해당 서버의 인증키 요구 등 수집할 수 없는 경우가 많다.

또한 동적인 기능을 지원하지 않는 경우가 많다.

Selenium

빅데이터 관련, 동적인 자료를 수집할 때 주로 사용한다.

Jsoup에 비해 속도는 느리지만 브라우저 드라이버를 사용하여 동적 데이터도 수집 가능하다.

[Java] 크롤링 crawling, 셀레니움 Selenium

Jsoup 사용법

  1. gradle dependency 추가

    implementation 'org.jsoup:jsoup:1.13.1'

    Jsoup의 주요 요소는 크게 다섯가지가 있다.

    클래스명설명
    DocumentJsoup을 이용해얻어온 결과 HTML 전체 문서
    ElementDocument의 HTML 요소
    ElementsElement가 모인 자료형. for나 while 등 반복문 사용이 가능하다.
    ConnectionJsoup의 connect 혹은 설정 메소드들을 이용해 만들어지는 객체, 연결을 하기 위한 정보를 담고 있다.
    ResponseJsoup가 URL에 접속해 얻어온 결과. Document와 다르게 status 코드, status 메시지나 charset같은 헤더 메시지와 쿠키등을 가지고 있다.

    Jsoup로 하는 작업은 크게 보았을 때 Connection 객체를 통해 URL에 접속하고(혹은 로컬 파일/문자열), Response 객체에서 세션ID같은 쿠키와 HTML Document를 얻어낸 후, Document의 Element들을 파싱하는 과정으로 나누어진다고 볼 수 있다.

  2. URL 접속해 결과 가져오기

    String crawlingURL = "http://www.cgv.co.kr/common/showtimes/iframeTheater.aspx?areacode=01&theatercode=0013&date=20211216&screencodes=&screenratingcode=&regioncode=";
    
            Connection conn = Jsoup.connect(crawlingURL);
            Document document = conn.get();
            System.out.println(document);

    crawlingURL 주소의 html 전체 내용이 document에 저장된다.

  3. 가져온 결과에서 원하는 값 파싱

    크롤링 하려는 페이지에서 크롬 개발자도구를 이용해 파싱하고자 하는 부분의 요소를 확인한 후, 다음 메서드들을 이용해 원하는 값을 파싱할 수 있다.

    • getElementByClass(String className)

      // class가 "col-times"인 데이터를 모두 가져온다
      Elements showTimeTablesForMovies = document.getElementsByClass("col-times");
    • Element.select(String selector)

      Elements element = elements.select("div.클래스명");
      Elements element = elements.select("div[class=\"클래스명\"]");
      Elements element = elements.select(".클래스명");
      • class로 가져올땐 div.class
      • id로 가져올때는 div#id
      • 속성으로 가져올땐 [src=ff]
      • elements.select("[href]") : href 속성을 가진 요소들을 선택
      Elements infoHall = showTimeTablesForHallType.select("div.info-hall li");        
      • class가 "info-hall"인 요소 하위에 li 태그의 내용들을 가져옴
    • getElementByTag(String tag)

    • getElementById(String id)

    • doc.text()

      String text = doc.text();

      문서에서 html tag를 모두 제거하고 순수 문자열만 얻고자 할때 사용

CGV 영화 상영시간 크롤링

페이지 구조

코드

public static void main(String[] args) throws IOException {
     // CGV 용산아이파크몰의 areaCode, theaterCode
        String areaCode = "01";
        String theaterCode = "0013";
        String date = "20211216";
        String crawlingURL = "http://www.cgv.co.kr/common/showtimes/iframeTheater.aspx?areacode="
                + areaCode
                + "&theatercode=" + theaterCode
                + "&date=" + date;

        // 영화별 상영관 스케줄들 파싱
        Elements showTimeTablesForMovies = document.getElementsByClass("col-times");
        ArrayList<MovieTime> movieTimes= new ArrayList<MovieTime>();
        for(Element showTimeTablesForMovie : showTimeTablesForMovies){

            String movieTitle = showTimeTablesForMovie.select(".info-movie a").text();

            Elements showTimeTablesForHallTypes = showTimeTablesForMovie.getElementsByClass("type-hall");
            // 상영관 별 영화 스케줄들 파싱
            for(Element showTimeTablesForHallType : showTimeTablesForHallTypes){
                // 상영관 정보
                Elements infoHall = showTimeTablesForHallType.select(".info-hall li");
                String hallType = infoHall.get(0).text();
                String hallName = infoHall.get(1).text();

                Elements infoTimeTables = showTimeTablesForHallType.select(".info-timetable li");
                Integer a = 0;
                for(Element availableTime : infoTimeTables){
                    String time = availableTime.getElementsByTag("em").text();
                    String availableSeats = availableTime.getElementsByTag("span").text();
                    String href = availableTime.getElementsByTag("a").attr("abs:href");

                    movieTimes.add(MovieTime.builder()
                                        .movieTitle(movieTitle)
                                        .hallType(hallType)
                                        .hallName(hallName)
                                        .time(time)
                                        .availableSeats(availableSeats)
                                        .build());
                }
            }
        }
        for(MovieTime movieTime:movieTimes){
            System.out.println(movieTime.toString());
        }
}

결과

참고

https://jsoup.org/

https://javafactory.tistory.com/1574

삽질노트

  1. iframe

http://www.cgv.co.kr/theaters/?areacode=01&theaterCode=0013&date=20211209

위 URL(CGV 예매 페이지 url)로 크롤링해온 내용에서, 내가 필요한 부분(상영 시간)을 찾아봤는데 결과가 없었음..알고보니 iframe이라는 요소를 이용해서 웹페이지 안에 다른 웹페이지를 삽입해 놓은 구조였어서 삽입한 페이지 주소로 다시 접근하니 결과 나옴

profile
삐약 응애

1개의 댓글

comment-user-thumbnail
2022년 6월 21일

혹시 iframe 웹페이지에 관한 접근을 막았을 경우에는 크롤링 하는 방법이 따로 있을까요?
전에는 iframe 주소를 따서 넣으면 해당 부분만 새창으로 열 수 있었는데,
지금은 아예 빈 화면으로만 뜨는걸 보니 접근을 막은건지, 좀 달라진건지 그렇더라구요

답글 달기