package craw;

import java.time.Duration;
import java.util.ArrayList;
import java.util.Set;

import org.openqa.selenium.By;
import org.openqa.selenium.Keys;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

import testDTO.Naver_Map_CrawlingDTO;

public class CrawlingTest10{
	public static ArrayList<Naver_Map_CrawlingDTO> crawling(String search,int page) {
		
		//page 는 무조건 있어야 하니
		//만약 0보다 작다면 1로 고정
		if(page <= 0) {
			page = 1;
		}
        // ChromeOptions 객체 생성
        ChromeOptions options = new ChromeOptions();

        // 헤드리스 모드 설정
//        options.addArguments("--headless");

        // 추가적인 옵션 설정 (선택 사항)
        options.addArguments("--disable-gpu"); // GPU 비활성화 (일부 환경에서 필요)
        options.addArguments("--window-size=1920,1080"); // 브라우저 창 크기 설정
        options.addArguments("--no-sandbox"); // 샌드박스 모드 비활성화 (Linux에서 권장)
        options.addArguments("--disable-dev-shm-usage"); // /dev/shm 사용 비활성화 (메모리 문제 해결)

		WebDriver driver = new ChromeDriver(options);
		//--------------------------------------------------------------------------------
		//최종적으로 저장할 공간
		ArrayList<Naver_Map_CrawlingDTO> datas = new ArrayList<Naver_Map_CrawlingDTO>();
		//가져온 이미지 주소를 담을 배열
		ArrayList<String> naver_map_climbing_img = new ArrayList<String>();
		//가져온 이름을 담을 배열
		ArrayList<String> naver_map_climbing_name = new ArrayList<String>();
		//가져온 주소를 담을 배열
		ArrayList<String> naver_map_climbing_address = new ArrayList<String>();
		
		//이미지 요소를 담을 변수
		WebElement climbing_img_Element  = null;
		//이름 요소를 담을 변수
		WebElement climbing_name_Element = null;
		//주소 div 태그를 열기 위함 요소를 담을 변수
		WebElement climbing_address_div_Element = null;
		//주소 요소를 담을 변수
		WebElement climbing_address_Element = null;

		//주소 담을 동안 div 태그를 클릭하여 스크롤이 내려가므로 필요가 없어졌음
		//JavascriptExecutor js = (JavascriptExecutor) driver;
		//--------------------------------------------------------------------------------
		
		// 주소 설정
		String url = "https://www.naver.com/";
		// 웹 페이지 접속
		driver.get(url);

		driver.manage().window().maximize();

		// 현재 ChromeDriver의 대기 시간 2초를 부여
		WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(3));

		//----------------------------------------------------------------------------------
		//네이버 지도를 들어가기 위한 준비
		
		//naver 접속 후 지도를 클릭
		WebElement map = wait.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("#shortcutArea > ul > li:nth-child(8) > a")));
		System.out.println("map로그 : "+map);
		map.click();

		//열린 창 OR 탭을 가져오는 코드
		Set<String> naver_map = driver.getWindowHandles();
		String current_naver_map = driver.getWindowHandle();

		// 새로 열린 창으로 전환하기 위한 for 문
		for (String window : naver_map) {
			//현재 열려 있는 창중 처음 열린 창과 다르다면 
			if (!window.equals(current_naver_map)) {
				//현재 창을 새로열린 창으로 변경하여 저장하고
				current_naver_map = window;
				//새로 열린 창으로 전환해줍니다.
				driver.switchTo().window(window);  // 새로운 창으로 전환
				break;//전환 후 for 문 종료
			}
		}

		//지도가 열렸다면 검색 input 태그를 불러와 줍니다.
		WebElement search_value = wait.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("div > div > div > .input_search")));
		//받아온 검색 값을 확인하기 위한 로그
		System.out.println("검색 로그 : "+search);
		search_value.sendKeys(search);
		search_value.sendKeys(Keys.ENTER);
		//----------------------------------------------------------------------------------
		
		//----------------------------------------------------------------------------------
		// Iframe 요소를 가져와줍니다.
		WebElement climbing_iframe = wait.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("#searchIframe")));
		System.out.println(climbing_iframe);
		// 찾은 Iframe 요소의 주소만 불러와 현재 창을 전환해 줍니다.
		driver.get(climbing_iframe.getAttribute("src"));
		//----------------------------------------------------------------------------------
		
		
		System.out.println("로그 : 크롤링 시작");
		for(int page_num = 0; page_num < page; page_num++) {
			System.out.println("--------------------------Iframe 페이지 요소 찾기----------------------------");
			//크롤링 성능을 올리기 위해 xPath로 이름 요소를 찾고 try catch는 페이지 이동 처음에 배치
			try {
				climbing_name_Element = wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("/html/body/div[3]/div/div[2]/div[1]/ul/li[1]/div[1]/div[2]/a[1]/div/div/span[1]")));
				System.out.println(climbing_name_Element.getText() + " 1 요소");
			}catch (Exception e) {
				climbing_name_Element = wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("html/body/div[3]/div/div[2]/div[1]/ul/li[1]/div[1]/div/a[1]/div/div/span[1]")));
				System.out.println(climbing_name_Element.getText() + " 2 요소");
			}
			System.out.println("-------------------------------------------------------------------");
			for (int i = 1; i < 40; i++) {
				//#_pcmap_list_scroll_container > ul > li:nth-child(1) > div.qbGlu > div.ouxiq > a:nth-child(1) > div > div > span.YwYLL
				climbing_name_Element = wait.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("#_pcmap_list_scroll_container > ul > li:nth-child("+i+") > div.qbGlu > div.ouxiq > a:nth-child(1) > div > div > span.YwYLL")));

				//이름 불러오기
				System.out.println(climbing_name_Element.getText());
				naver_map_climbing_name.add(climbing_name_Element.getText());

				//상세 주소를 가져오기 위해 주소요소를 클릭
				climbing_address_div_Element = wait.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("li:nth-child("+i+") > div.qbGlu > div.ouxiq > div > div > span:nth-child(2) > a")));
				climbing_address_div_Element.click();

				//li:nth-child(1) > div.qbGlu > div.ouxiq > div > div > div > div > div:nth-child(1)
				climbing_address_Element = wait.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("li:nth-child("+i+") > div.qbGlu > div.ouxiq > div > div > div > div > div:nth-child(1)")));
				
				//주소 불러오기
				System.out.println(climbing_address_Element.getText());
				naver_map_climbing_address.add(climbing_address_Element.getText().replace("지번", "").replace("도로명", "").replace("복사", ""));

				//이미지 불러오기
				try {
					//#_pcmap_list_scroll_container > ul > li:nth-child(1) > div.qbGlu > div.TTfa9 > a > img
					climbing_img_Element = wait.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("li:nth-child("+i+") > div.qbGlu > div.TTfa9 > a > img")));
					//현재 찾은 img 요소가 어떤것인지 확인하기 위해 작성
					System.out.println("현재 요소 : "+climbing_img_Element);
					System.out.println(climbing_img_Element.getAttribute("src"));
					naver_map_climbing_img.add(climbing_img_Element.getAttribute("src"));
				}catch (Exception e) {
					try {
						//#_pcmap_list_scroll_container > ul > li:nth-child(2) > div.qbGlu > div.TTfa9 > a > div > img
						climbing_img_Element = wait.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("li:nth-child("+i+") > div.qbGlu > div.TTfa9 > a > div > img")));
						//현재 찾은 img 요소가 어떤것인지 확인하기 위해 작성
						System.out.println("현재 요소 : "+climbing_img_Element);
						System.out.println(climbing_img_Element.getAttribute("src"));
						naver_map_climbing_img.add(climbing_img_Element.getAttribute("src"));
					}catch (Exception ex) {
						naver_map_climbing_img.add("");
						System.out.println("img 태그 오류 발생 저장X : "+i+"번");
					}
				}
				
				//div 태그 클릭해서 스크롤 이동이 가능하므로 JavaScript가 필요 없습니다.
				//js.executeScript("arguments[0].scrollIntoView(true);", climbing_name_Element);

			}
			

			try {
				WebElement next_map = wait.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("#app-root > div > div.XUrfU > div.zRM9F > a:nth-child(7)")));
				next_map.click();				
			} catch (Exception e) {
				//페이지 네이션을 선택할때 오류가 발생한다면 종료
				break;
			}
		}
		//실제 데이터 저장하기 위한 for문
		for (int i = 0; i < naver_map_climbing_name.size(); i++) {
			Naver_Map_CrawlingDTO data = new Naver_Map_CrawlingDTO();
			data.setNaver_map_climbing_address(naver_map_climbing_address.get(i).toString());
			data.setNaver_map_climbing_img(naver_map_climbing_img.get(i));
			data.setNaver_map_climbing_name(naver_map_climbing_name.get(i));
			// 저장되고 있는지 확인용 코드
			//System.out.println("datas 저장중 "+naver_map_climbing_img.get(i));
			//이미지는 필수로 필요하니 이미지가 없는 요소들은 실질적으로 저장하지 않음
			if(!naver_map_climbing_img.get(i).equals("")) {
				datas.add(data);				
			}

		}

		// 아래 두 코드는 탭 OR 창 전환 후 원래 창으로 돌아오는 코드이나.
		// 지도 크롤링 완료 후 
		// 기본 컨텐츠로 전환
		//driver.switchTo().defaultContent();
		// 작업이 끝난 후, 원래 창으로 돌아오기
		//driver.switchTo().window(current_naver_map);

		//드라이버 종료
		driver.quit();
		System.out.println(datas);
		return datas;
	}
	//	크롤링 확인용
	public static void main(String[] args) {
		CrawlingTest10.crawling("클라이밍",2);
	}
}
728x90

'추가 공부 > Web' 카테고리의 다른 글

CKEditor5 사용해보기 1  (1) 2024.09.17
CKEditor5 연동  (1) 2024.09.15
JAVA에서 mkdir 사용해보기  (0) 2024.09.10
JSP Selenium 사용해보기 2  (3) 2024.09.03
JSP Selenium 사용해보기 1  (0) 2024.09.02
개발자가 되고 싶은 곰