웹크롤링을 통하여 CGV의 현재 상영 중인 영화 목록들을 가져오려고 하며
가져오려는 정보들은 영화 제목, 포스터, 장르이다.
아래 페이지에서 정보들을 가져와 DB에 데이터를 저장하려 한다.
http://www.cgv.co.kr/movies/?lt=1&ft=0
영화 그 이상의 감동. CGV
멘 예매율0.3% 73% 2022.07.13 개봉 예매
www.cgv.co.kr
SQL을 이용해 테이블을 만들고 자바로 sql문을 작성해 데이터를 저장할 준비를 해두었다.
CREATE TABLE MOVIE(
MID INT PRIMARY KEY,
TITLE VARCHAR(100) NOT NULL,
IMG VARCHAR(1000) NOT NULL,
CATEGORY VARCHAR(100),
BOOKCNT INT DEFAULT 0
);
public class JDBCUtil { // 편의성을 위한 드라이버 연결, 해제 클래스
static final String driverName="oracle.jdbc.driver.OracleDriver";
static final String url="jdbc:oracle:thin:@localhost:1521:xe";
static final String user="kim";
static final String password="1234";
public static Connection connect() {
Connection conn = null;
try {
Class.forName(driverName);
conn = DriverManager.getConnection(url, user, password);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return conn;
}
public static void disconnect(PreparedStatement pstmt,Connection conn) {
try {
pstmt.close();
conn.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
final String sql_insert = "INSERT INTO CGV VALUES((SELECT NVL(MAX(CID),0)+1 FROM CGV),?,?,?,?)";
// 크롤링하여 받아온 데이터를 DB에 저장
public boolean insert(CgvVO vo) {// 받아온 객체를
conn = JDBCUtil.connect(); // 드라이버 연결
try {
pstmt = conn.prepareStatement(sql_insert);// sql insert 쿼리문에
pstmt.setString(1, vo.getTitle()); // 영화제목
pstmt.setString(2, vo.getImage()); // 영화포스터
pstmt.setString(3, vo.getGenre()); // 장르
pstmt.executeUpdate();// 넣어준다
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
} finally {
JDBCUtil.disconnect(pstmt, conn); // 드라이버 연결 해제
}
return true;
}

영화 제목의 정보는 <a>태그의 strong이 title 클래스로 가지고 있는 것을 확인할 수 있으며

영화 포스터의 정보는 <span> 태그의 box-image 클래스 안에 img가 속성 값 src로 가지고 있는 것을 확인할 수 있다.

해당 페이지내에서 영화 제목과 포스터 정보는 얻을 수 있지만 장르의 정보는 찾을 수 없다.
장르의 정보는 각각의 해당 영화의 상세정보 페이지에서 찾을 수 있으며
무비차트 페이지에서 각 영화의 상세정보 페이지로 넘어가 장르가 들어있는 정보를 가져와야 한다.

상세페이지로 넘어오면 장르의 정보를 확인할 수 있고
div > dl > dt로 있는 것을 확인할 수 있다. 하지만 dt태그로 존재하는 값이
감독, 배우, 장르, 기본, 개봉 등이 있기 때문에 추후 장르 정보만 정제해주는 과정을 한번 더 거쳐주어야 한다.

웹페이지를 정보를 자바로 가져오기 위해서는 Jsoup(외부. jar파일) 클래스의 connect() 메서드를
이용하여 자바와 웹페이지를 연결해 주어야 하며 이후 get() 메서드로 해당 url의 정보를 가져온다.
get() 메서드의 아웃풋 값은 Document 이기 때문에 Document 객체(doc)에 정보를 담아준다.
String cgvUrl = "http://www.cgv.co.kr/movies/?lt=1&ft=0"; // 크롤링하려는 페이지의 url
Document doc = null; // Document 객체 생성
try {
doc = Jsoup.connect(cgvUrl).get(); // Jsoup 클래스로 url 연결하여 정보를 doc에 담음
} catch (IOException e) {
e.printStackTrace();
}
이후 해당 url 내에서 원하는 정보(영화 제목, 포스터, 장르)를 doc의 select() 메서드로 추출하고
String title = "strong.title"; // 영화제목 (title 클래스)
Elements eles1 = doc.select(title); // 해당 url에서 영화 제목 정보만 eles1에 담음
String img = ".thumb-image > img"; // 이미지 (속성값 src를 가지고 있는 img)
Elements eles2 = doc.select(img); // 해당 url에서 영화 이미지 정보만 eles2에 담음
String genre = "div.box-image>a"; // 장르(장르를 추출하기 위한 상세페이지)
Elements eles3 = doc.select(category); // 해당 url에서 영화 장르를 추출하기위한 정보를 eles3에 담음
// 장르 정보가 완전히 정제되어 있지 않음
// 영화 상세정보 페이지의 주소가 있는 a태그
iterator() 메서드로 해당 정보들을 요소별로 분리하여 준다.
iterator() 메서드의 아웃풋 값은 Element 타입으로 제한된 Iterator 컬렉션 프레임워크 배열이기 때문에
해당 정보들을 Iterator <Element> 객체에 담아준다.
Iterator<Element> itr1 = eles1.iterator(); // 영화제목 정보를 요소 별로 분리
Iterator<Element> itr2 = eles2.iterator(); // 이미지 정보를 요소 별로 분리
Iterator<Element> itr3 = eles3.iterator(); // 상세페이지 정보를 요소 별로 분리
Iterator가 가지고 있는 next() 메서드를 통하여 배열의 정보를 요소 별로 얻을 수 있으며
영화 제목의 경우 text() 메서드를 사용해 태그를 제외한 영화 제목만을 정제해준다.
CgvVO vo = new CgvVO(); // 정보를 담을 객체
CgvDAO cDAO = new CgvDAO(); // 정보를 DB로 넘겨줄 메서드를 가진 객체
String title2 = itr1.next().text(); // 태그를 제외한 영화 제목 정보를 담음
포스터 이미지의 경우 next() 메서드 후 attr() 메서드로 속성 값 src(포스터 이미지의 url)를 추출해준다.
url의 이미지를 내 컴퓨터에 저장하기 위해서는 URL, InputStream, OutputStream 클래스를 사용해야 한다.
URL 클래스 객체에 추출해낸 이미지 정보를 담아주고 url 객체의 openStream() 메서드를 통하여
포트를 열고 IN 클래스 객체에 url 정보(포스터 이미지)를 담아준다.
이후 OUT클래스 객체에 저장 경로와 생성하길 원하는 파일명을 입력해준다.
입력이 완료되었다면 in 객체의 read() 메서드로 이미지를 읽어 들이고
out 객체의 write() 메서드로 읽어 들인 데이터를 경로에 저장한다.
저장이 끝난 후에는 포트를 닫아준다.
String img2 = itr2.next().attr("src");
// 영화 이미지 정보의 속성값인 src(이미지 주소)를 담음
URL url = null; // URL 객체생성
InputStream in = null; // InputStream 객체 생성
OutputStream out = null; // OutputStream 객체 생성
url = new URL(img2);
// url 객체에 이미지 주소를 담음
in = url.openStream();
// in 객체에 url 정보 담음(받고싶은 데이터 연결), 열림 1
out = new FileOutputStream("D:\\0607Park\\포스터\\"+이름+".png");
// out 객체에 저장경로(저장을 원하는 위치) 입력
// 생성하길 원하는 파일명 입력
while(true) {
int data = in.read(); // in 객체로 해당 이미지를 읽어들임
if(data==-1) { // 더이상 읽을것이 없으면 멈춤
break;
}
out.write(data); // 읽어들인 데이터를 경로에 작성
}
in.close(); // 저장이 끝난후 사용한 객체는 close, 닫음 1
out.close();
이제 장르 정보를 가져오기 위해 상세페이지 url을 추출해주고 영화마다 ? 뒤에 붙는 midindex 값이
다르기 때문에 각 영화의 midindex 값을 추출해준다.
String genre2 = itr3.next().attr("href");
// 장르를 정제하기 위해 속성값 href(상세정보 페이지) 추출
String str = "https://www.cgv.co.kr/movies/detail-view/?"+genre2.substring(21,genre2.length());
// 추출한 주소에서 다시 한번 원하는 영화의 midindex 추출 (개별 영화의 상세정보 페이지)
이후 추출한 각 영화의 상세정보 페이지에 연결하여 다시 한번 doc2에 정보를 담아준다.
String cgvUrl2 = str; // 개별 영화의 상세정보 페이지
Document doc2 = null;
try {
doc2 = Jsoup.connect(cgvUrl2).get(); // 상세정보 페이지에 연결하여 정보를 담음
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
미리 확인해둔 영화 소개 정보를 요소별로 배열에 담아준다.
String genre3 = "div>dl>dt"; // 감독, 배우, 장르 등등
Elements eles4 = doc2.select(genre3); // 영화 소개정보(장르포함)만 eles4에 담음
Iterator<Element> itr4 = eles4.iterator(); // 영화정보를 요소별로 분리
이 후 태그를 제외한 영화 소개 정보를 분리해낸 후 indexOf() 메서드를 사용하여
장르 정보만 추출해 준비해둔 객체에 담아준다.
String genre4 = itr4.next().text(); // 태그를 제외한 영화정보
String a = "장르 : ";
int c = genre4.indexOf(a); // 장르만 추출해내기 위해 사용(장르가 아니면 -1 반환)
if(c!=-1) { // 장르 정보만 추출하여 객체에 입력
System.out.println(title2);
System.out.println(img2);
System.out.println(genre4.substring(5, genre4.length()));
System.out.println();
vo.setGenre(genre4.substring(5, genre4.length()));
}
제목과 이미지 정보도 마찬가지로 객체에 담아 작성해둔 insert() 메서드로 DB에 정보를 담아준다.
vo.setTitle(title2); // 객체에 영화제목 입력
vo.setImage(img2); // 이미지 입력
cDAO.insert(vo); // DAO의 insert 함수로 DB에 영화정보 추가
코드 분리의 편의성을 위해 while문을 생략하였지만 위 과정에 while문을 사용하여 해당 페이지 내의
영화 제목, 포스터 이미지, 장르 정보를 모두 DB에 저장할 수 있다.
'Java > study' 카테고리의 다른 글
| 웹크롤링하여 DB에 데이터 넣기 (0) | 2022.07.14 |
|---|---|
| SQL을 활용하여 MVC 응용 (0) | 2022.07.14 |
| MVC 모델을 이용한 자판기 프로그램 (0) | 2022.07.13 |
| PrepareStatement 이용하기 (0) | 2022.07.05 |
| JAVA에 DB연동하기 (0) | 2022.07.04 |