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로 하니까 잘 들어간다.
+ 네이버 영화 리뷰 크롤링 내용도 추가된 크롤링 설명서 파일 첨부
'PROJECT' 카테고리의 다른 글
[React] 넷플릭스 클론 프로젝트 [1] - 들어가며 (0) | 2025.01.20 |
---|---|
[Spring] 스프링 프로젝트 - 웹 커뮤니티 'WANDERIZM' (0) | 2021.12.08 |
[JAVA] 웹 프로젝트 - 영화 리뷰 웹 사이트 'Film-E' (0) | 2021.10.20 |
[HTML/CSS/JavaScript/jQuery] 미디어쿼리를 이용한 반응형 웹 제작 - 메뉴바 / Footer (0) | 2021.08.23 |
[JAVA] 항공권 예매 프로젝트 (M-V-C) (0) | 2021.08.04 |