CGVExample.java
10.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import java.awt.*;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;
import java.util.*;
class CGVMovieInfo { //CGV 영화 정보를 담는 class
private String title; //영화 제목
private int rank; //CGV 내 예매율 순위
private float score; //예매율
private String GoldenEgg; //골든에그 지수
private String movieCode; //CGV 고유 영화코드 - 예매 사이트 연결 시 사용
public CGVMovieInfo(String title, int rank, float score, String GoldenEgg, String movieCode) {
this.title = title;
this.rank = rank;
this.score = score;
this.GoldenEgg = GoldenEgg;
this.movieCode = movieCode;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public int getRank() {
return rank;
}
public void setRank(int rank) {
this.rank = rank;
}
public float getScore() {
return score;
}
public void setScore(float score) {
this.score = score;
}
public String getGoldenEgg() {
return GoldenEgg;
}
public void setGoldenEgg(String goldenEgg) {
GoldenEgg = goldenEgg;
}
public String getMovieCode() {
return movieCode;
}
public void setMovieCode(String movieCode) {
this.movieCode = movieCode;
}
public String getLink() {
return String.format("https://www.cgv.co.kr/ticket/?MOVIE_CD=%s&MOVIE_CD_GROUP=%s", this.movieCode, this.movieCode);
}
public void printMovieInfo(){
System.out.println("-------------------------------------------------------");
System.out.println(this.rank + " : " + this.title);
System.out.println("예매율 : " + this.score + "%");
System.out.println("골든에그지수 : " + this.GoldenEgg);
System.out.println("영화코드 : " + this.movieCode);
System.out.println("-------------------------------------------------------");
}
}
public class CGVExample {
public static final String WEB_DRIVER_ID = "webdriver.chrome.driver"; //드라이버 ID
public static final String WEB_DRIVER_PATH = "WebCrawling/chromedriver"; //드라이버 경로
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String url_movies = "https://www.cgv.co.kr/movies/?lt=1&ft=1"; //끝의 쿼리 0은 개봉 전 영화도 포함하는 것. 예매율 순위 가져오기
String url_theaters = "https://www.cgv.co.kr/theaters"; //영화관 정보 가져오는 링크.
String url_ticketing = "https://www.cgv.co.kr/ticket/"; //상영중인 영화 정보 가져오는 링크.
ArrayList<LinkedHashMap<String, String>> theaters = new ArrayList<>(); //지역별 영화관 HashMap(Key: 영화관, value:영화관별 고유코드)으로 이루어진 Arraylist
ArrayList<CGVMovieInfo> Movies = new ArrayList<>(); //CGVMovieInfo 클래스의 인스턴스들을 원소로 가지는 Arraylist
// 여기부터 영화관 및 영화관별 고유코드 가져오는 부분.
try{ //드라이버 설정
System.setProperty(WEB_DRIVER_ID,WEB_DRIVER_PATH);
}catch (Exception e){
e.printStackTrace();
}
ChromeOptions options = new ChromeOptions(); //크롬 설정을 담은 객체 생성
options.addArguments("headless"); //브라우저가 눈에 보이지 않고 컴파일러 내부에서 작동됨.
WebDriver driver_theaters = new ChromeDriver(options); //위에서 설정한 옵션을 파라미터로 넘겨주고, 드라이버 객체 생성.
driver_theaters.get(url_theaters); //WebDriver 객체를 해당 URL로 이동시킨다.
//브라우저 이동시 생기는 로드시간을 기다린다.
//HTTP 응답속도 보다 자바의 컴파일 속도가 더 빠르기 때문에 임의적으로 1초를 대기한다.
try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}
//영화관 및 영화관에 대응되는 영화관별 고유 코드 가져오기.
List<WebElement> area = driver_theaters.findElements(By.className("area"));
for (WebElement elem : area) {
LinkedHashMap<String, String> theaters_info = new LinkedHashMap<>();
List<WebElement> theaters_by_area = elem.findElements(By.tagName("a"));
for (WebElement theater : theaters_by_area) {
String theater_name = theater.getAttribute("title").replace("CGV", "");
String theater_code = theater.getAttribute("href").replaceAll("(.+(?<=theaterCode=))|(.+(?<=theatercode=))", "").substring(0,4);
theaters_info.put(theater_name, theater_code);
}
theaters.add(theaters_info);
}
try {
driver_theaters.close(); //드라이버 연결 해제
driver_theaters.quit(); //프로세스 종료
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
//여기부터 예매율 순위 가져오는 부분
Document doc_movies;
try {
doc_movies = Jsoup.connect(url_movies).get();
//예매율 Top19까지의 영화의 정보를 가져옴.
Elements elements1 = doc_movies.select("div.sect-movie-chart");
Iterator<Element> rank = elements1.select("strong.rank").iterator();
Iterator<Element> title = elements1.select("strong.title").iterator();
Iterator<Element> score = elements1.select("strong.percent").iterator();
Iterator<Element> GoldenEgg = elements1.select("span.percent").iterator();
Iterator<Element> link = elements1.select("a.link-reservation").iterator();
//영화 제목, 순위, 예매율, 영화 코드, 골든에그 지수를 가져와 CGVMovieInfo 객체 생성자에 파라미터로 넘겨주고, 인스턴스를 받아옴.
while(title.hasNext()){
String newTitle = title.next().text();
int newRank = Integer.parseInt(rank.next().text().replace("No.",""));
float newScore = Float.parseFloat(score.next().text().replace("예매율", "").replace("%", ""));
String newCode = link.next().attr("href").replaceAll("[^0-9]", "").substring(0,8);
CGVMovieInfo newMovie = new CGVMovieInfo(newTitle, newRank, newScore, GoldenEgg.next().text(), newCode);
Movies.add(newMovie);
}
}catch(IOException e){
e.printStackTrace();
}
for (CGVMovieInfo elem : Movies) {
//elem.printMovieInfo();
System.out.println(elem.getRank() + " : " + elem.getTitle());
}
//영화 이름(Integer 선택지), 영화관 지역 코드, 영화관 이름, 관람 일자 입력 시, (시간 선택 가능한) 예매 사이트로 이동.
System.out.print("예매하고 싶은 영화의 순위를 입력하세요 : ");
int inputRank = scanner.nextInt();
System.out.print("지역 코드를 입력하세요 : ");
int regionCode = scanner.nextInt();
System.out.print("영화관명을 입력하세요 : ");
String theaterName = scanner.next();
String theaterCode = theaters.get(regionCode).get(theaterName);
System.out.print("관람 일자를 입력하세요 : ");
int date = scanner.nextInt();
String otherFormat = String.format("THEATER_CD=%s&PLAY_YMD=%s", theaterCode, date);
url_ticketing += ("?" + otherFormat);
//예매 가능한 영화 리스트를 얻기 위해 빠른 예매 사이트로 이동.
WebDriver driver_ticketing = new ChromeDriver();
driver_ticketing.get(url_ticketing);
try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}
//Frame 전환
WebElement selecting_area = driver_ticketing.switchTo().frame("ticket_iframe").findElement(By.className("theater-area-list"));
List<WebElement> selected_areas_list = selecting_area.findElements(By.cssSelector("ul > li > a > span.name"));
//지역 코드에 맞게 list element click
selected_areas_list.get(regionCode).click();
try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}
//선택한 지역에 대응되는 영화관 정보 가져오기
WebElement selecting_theaters = selecting_area.findElement(By.cssSelector("ul > li.selected > div > ul"));
List<WebElement> selected_theaters_list = selecting_theaters.findElements(By.tagName("li"));
//프로그램 내부에서 가지고 있는 영화관코드와 웹에서 받아온 영화관코드가 일치하는 경우, selected_theaters_list element 클릭
for(WebElement theater_element : selected_theaters_list) {
if(theater_element.getAttribute("theater_cd").equals(theaterCode)){
theater_element.click();
try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}
break;
}
}
//선택한 영화관에서, 선택한 일자에 상영하는 영화 목록 들고오기
WebElement selecting_movies = driver_ticketing.findElement(By.className("movie-select"));
List<WebElement> selected_movies_list = selecting_movies.findElements(By.cssSelector("#movie_list > ul > li"));
LinkedHashMap<String, String> accessible_movies = new LinkedHashMap<>();
//선택불가를 제외한 영화 제목 출력
for(WebElement movie_element : selected_movies_list){
String movie_enabled = movie_element.getAttribute("class");
if(movie_enabled.endsWith("dimmed"))
break;
else{
String title = movie_element.findElement(By.cssSelector("span.text")).getText();
String code = movie_element.getAttribute("movie_cd_group");
accessible_movies.put(title, code);
System.out.println(title + " : " + code);
}
}
try{
driver_ticketing.close(); //드라이버 연결 해제
driver_ticketing.quit(); //프로세스 종료
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
try{
Desktop.getDesktop().browse(new URI(Movies.get(inputRank - 1).getLink() + "&" + otherFormat));
}
catch(IndexOutOfBoundsException | URISyntaxException | IOException e){
System.out.println(e.getClass());
}
}
}