본문 바로가기
PROJECT

[JAVA] 네이버 영화 크롤링하여 DB에 저장하기 (영화 정보 및 리뷰)

by sngynhy 2021. 10. 1.

https://movie.naver.com/movie/running/current.naver

 

현재상영작 : 네이버 영화

상영 중 영화의 예매율/평점/좋아요 순 정보 제공.

movie.naver.com

 

 

크롤링 과정

1. 아래 페이지에서 각 포스터 이미지 클릭을 하면 해당 영화의 세부 정보 페이지로 넘어간다.

 

String url = "https://movie.naver.com/movie/running/current.naver"; // 현재 상영 영화 페이지 url
String url2 = "https://movie.naver.com"; // 다음 영화로 넘어갈 때 사용

Document doc = Jsoup.connect(url).get();
Elements imgUrl = doc.select(".thumb"); // 각 이미지 url 목록

for (int i=0; i<imgUrl.size(); i++) {
	doc2 = Jsoup.connect(url2 + imgUrl.get(i).select("a").attr("href")).get();
	// a태그 href 속성값 추출하여 url2과 합치기
}

 

2. 클릭 시 이동되는 해당 영화의 세부 정보 페이지에서

다음의 정보가 모두 mv_info_area 클래스에 포함되어있고,

여기서 내가 필요한 것은 포스터, 영화제목, 장르, 개봉날짜인데

장르, 제작국가, 러닝타임, 개봉날짜가 아래와 같이 하나의 개요로 묶여있다.

(간혹 장르가 빠진 영화가 있는데 이런 경우는 제외함 -> if문 continue로 처리)

 

포스터는 이미지 url을 그대로 DB에 넣을거라 img태그의 src를 추출하여 저장

(src를 저 상태로 저장하게 되면 이미지가 너무 작아서 jpg 뒷 부분은 잘라서 저장함)

	Element el = doc2.select(".mv_info_area").get(0);
	String title = el.select(".h_movie > a").first().text(); // 타이틀
	System.out.println("타이틀: " + title);

	Elements info = el.select(".info_spec > dd").first().select("span"); // 영화 정보 - 장르, 제작국, 러닝타임, 개봉날짜
//	System.out.println("info : " + info);
				
	String genre = null; // 장르
	String country = null; // 제작국
	String runtime = null; // 러닝타임
	String date = null; // 개봉 날짜
				
	if (info.size() != 4) { // 장르가 없는 경우는 제외
		continue;
	}
    
	for (int j=0; j<info.size(); j++) { // 장르, 제작국, 러닝타임, 개봉날짜
//		String a = info.get(j).text();
//		System.out.println(j + " : " + a);
		genre = info.get(0).text();
		country = info.get(1).text();
		runtime = info.get(2).text();
		date = info.get(3).text();
	}

//	System.out.println(date.indexOf("개"));
	date = date.substring(0,11);
	date = date.replace(".", "/");
	date = date.replace(" ", "");

	System.out.println("장르: " + genre);
	System.out.println("제작국: " + country);
	System.out.println("러닝타임: " + runtime);
	System.out.println("개봉날짜: " + date);
    
	String poster = el.select(".poster img").attr("src"); // 영화 포스터 URL
	poster = poster.substring(0,poster.lastIndexOf("?"));
	System.out.println("포스터: " + poster);

 

3. 다음으로는 줄거리인데 줄거리가 없는 영화도 있어서 그런 경우 null로 처리했다.

String summary = doc2.select(".con_tx").size() > 0 ? doc2.select(".con_tx").first().text() : null; // 줄거리
System.out.println("줄거리: " + summary);

 

 

[결과]

 

 

[최종 코드]

package crawling;

import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import model.common.JDBC;

public class Crawilng {
	
	 public static void main(String[] args) {
		 
		 Connection conn = JDBC.getConnection();
		 PreparedStatement pstmt = null;
		 
		 String url = "https://movie.naver.com/movie/running/current.naver"; // 영화 리스트
		 String url2 = "https://movie.naver.com";
		
		 Document doc = null;
		 Document doc2 = null;
		 
		 
		try {
			doc = Jsoup.connect(url).get();
			Elements imgUrl = doc.select(".thumb"); // 각 이미지 url 목록
//			System.out.println("imgUrl" + imgUrl);
//			System.out.println(imgUrl.size());
			for (int i=0; i<3; i++) {
				doc2 = Jsoup.connect(url2 + imgUrl.get(i).select("a").attr("href")).get(); // 각 이미지 클릭 시 이동되는 해당 영화 정보 페이지 document
				
				Element el = doc2.select(".mv_info_area").get(0);
				String title = el.select(".h_movie > a").first().text(); // 타이틀
				System.out.println("타이틀: " + title);

				Elements info = el.select(".info_spec > dd").first().select("span"); // 영화 정보 - 장르, 제작국, 러닝타임, 개봉날짜
//				System.out.println("info : " + info);
				
				String genre = null; // 장르
				String country = null; // 제작국
				String runtime = null; // 러닝타임
				String date = null; // 개봉 날짜
				
				if (info.size() != 4) {
					continue;
				}
				for (int j=0; j<info.size(); j++) { // 장르, 제작국, 러닝타임, 개봉날짜
//					String a = info.get(j).text();
//					System.out.println(j + " : " + a);
					genre = info.get(0).text();
					country = info.get(1).text();
					runtime = info.get(2).text();
					date = info.get(3).text();
				}
				
				if (genre.indexOf(",") > 0) { // 장르 여러개일 경우 맨 첫번째 값만 저장
					genre = genre.substring(0, genre.indexOf(","));
				}
				
//				System.out.println(date.indexOf("개"));
				date = date.substring(0,11);
				date = date.replace(".", "/");
				date = date.replace(" ", "");
				
				System.out.println("장르: " + genre);
				System.out.println("제작국: " + country);
				System.out.println("러닝타임: " + runtime);
				System.out.println("개봉날짜: " + date);
				
				String summary = doc2.select(".con_tx").size() > 0 ? doc2.select(".con_tx").first().text() : null; // 줄거리
				System.out.println("줄거리: " + summary);
				
				String poster = el.select(".poster img").attr("src"); // 영화 포스터 URL
				poster = poster.substring(0,poster.lastIndexOf("?"));
				System.out.println("포스터: " + poster);
				
				System.out.println();
				
				// insert into movie2 values (mpk, 'title', 'summary', 'genre', to_date('2021/09/29', 'YYYY/MM/DD'), '포스터URL');
				pstmt = conn.prepareStatement("INSERT INTO MOVIE2 VALUES (nvl((select max(mpk) from movie2),0)+1,?,?,?,to_date(?, 'YYYY/MM/DD'),?)");
				pstmt.setString(1, title);
				pstmt.setString(2, summary);
				pstmt.setString(3, genre);
				pstmt.setString(4, date);
				pstmt.setString(5, poster);
				pstmt.executeUpdate();
				
			}
			
		} catch (IOException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			JDBC.close(conn, pstmt);
		}

    }
}

 

[DB]

JNDI로 시도했다가 실패해서 JDBC로 하니까 잘 들어간다.

 

 

+ 네이버 영화 리뷰 크롤링 내용도 추가된 크롤링 설명서 파일 첨부

크롤링_설명서.pdf
7.28MB