코딩항해기

[API] JAVA - 동적크롤링 (셀레니움4 Selenium +WebDriverManager) 본문

기타/API

[API] JAVA - 동적크롤링 (셀레니움4 Selenium +WebDriverManager)

miniBcake 2024. 9. 2. 15:18

 

정적크롤링하기 (jsoup)

 

[API] JAVA - 정적 크롤링 (jsoup API / Eclipse)

크롤링스크래핑웹페이지, 또는 웹사이트에서 데이터를 수집한다.크롤링수집한 데이터를 가공한다. (스크래핑과 세트이므로 스크래핑을 포함해서 이야기하는 경우가 많다.)웹 크롤링크롤링을

minibcake.tistory.com

 

 

정적페이지 동적페이지

정적페이지는 서버에서 생성된 후 변경되지 않는 페이지를 의미한다. 컨텐츠가 페이지에 고정되어있어 사용자가 요청할 때마다 동일한 내용을 제공한다. 반면 동적페이지는 사용자의 요청에 따라 서버에서 실시간으로 생성되거나 변경되는 페이지다. 사용자의 입력, 데이터베이스 등을 바탕으로 컨텐츠가 동적으로 생성된다.

 

jsoup은 정적 페이지만 크롤링 할 수 있고, 셀레니움은 동적 페이지도 크롤링이 가능하다.

 

 

셀레니움으로 티스토리 동적 크롤링하기

크롤링할 대상 결정

셀레니움으로 동적크롤링을 하는 법을 정리하기 위해 대상 페이지로 티스토리로 결정했다.

대상 페이지 : https://www.Tistory.com

티스토리 페이지를 살펴보니 다양한 동적 컨텐츠가 있는데, 그 중 strong.tit_g를 크롤링하면 적당할 것 같다.

 

 

셀레니움4 jar 다운로드

https://www.selenium.dev/downloads/

 

Downloads

Downloads Below is where you can find the latest releases of all the Selenium components. You can also find a list of previous releases, source code, and additional information for Maven users.

www.selenium.dev

 

들어오면 이런 페이지가 뜨는데, 이번 정리글에서는 하단의 grid jar파일을 이용해 크롤링할 예정이다.

다운로드 받으면 하나의 jar파일이 받아진다. 이 jar파일을 크롤링할 웹 프로젝트에 buildpath해준다.

 

WebDriverManager jar 다운로드

그리고, 하나의 api가 더 필요하다. WebDriverManager인데, WebDriverManager를 사용하지 않는다면 버전마다 각각의 드라이버를 업데이트하며 연결해 사용해야한다. 굉장히 번거롭고, 작업환경마다 다른 드라이버를 연결해야하므로 불편하다. 그 때 드라이버 관리를 도와주는 api가 WebDriverManager다. WebDriverManager를 쓰면 자동으로 연결드라이버가 관리된다.

 

https://jar-download.com/artifact-search/webdrivermanager#google_vignette

 

Download webdrivermanager JAR file with all dependencies

io.github.bonigarcia webdrivermanager 5.9.2 compile group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.9.2' //Thanks for using https://jar-download.com libraryDependencies += "io.github.bonigarcia" % "webdrivermanager" % "5.9.2" //Thanks

jar-download.com

 

여기서 다운로드 받아 이 jar파일 역시 전부 buildpath하면 된다.

그럼 작업환경은 세팅 완료된 것으로 이제 코드를 작성할 수 있다.

 

코드 작성

package seleniumPractice;

import java.time.Duration;
import java.util.List;

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.support.ui.WebDriverWait;

import io.github.bonigarcia.wdm.WebDriverManager;

public class Practice {
	public static WebDriver driver;
	public static final String URL = "https://www.Tistory.com";
	public static final String CSS_ELEMENTS = "strong.tit_g";

	public static void main(String[] args) {
		try {
			// 크롬 드라이버 경로 설정
			//System.setProperty("webdriver.chrome.driver", "D:\\koreaIT\\cordingProgram\\chromedriver_win32\\chromedriver.exe"); //크롬드라이버 다운로드받아서 수동으로 연결하는 방법
			WebDriverManager.chromedriver().setup();
			//WebDriverManager를 통해 버전 관리를 용이하게 하는 방법

			// 크롬 드라이버 객체 생성 (크롬을 이용해 크롤링)
			driver = new ChromeDriver();
			
			// Tistory 웹사이트로 이동
			driver.get(URL);

			// 명시적대기 15초 대기
			//WebDriverWait wait = new WebDriverWait(driver, 15); 
			WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(15)); //셀레니움4부터는 Duration로 시간 세팅함

			// 특정 요소가 나타날 때까지 대기
			WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector(CSS_ELEMENTS)));
			// visibilityOfElementLocated 조건이 만족될 때까지 최대 15초간 대기

			// 여기서 필요한 추가 작업들 수행 (로그인, 탐색 등)
			// 크롤링
			List<WebElement> titles = driver.findElements(By.cssSelector(CSS_ELEMENTS)); // 해당 선택된 요소를 크롤링

			// 제목 출력
			for (WebElement title : titles) {
				System.out.println("게시물 제목: " + title.getText());
			}

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			// 모든 작업이 마무리 되면 브라우저 종료 (모든 창 닫기)
			if (driver != null) {
				driver.quit();
			}
		}
	}
}

 

이때 대기하는 부분을 작성할 때 버전마다 방식이 미묘하게 달라 애를 많이 먹었다.

(작성된 방식 외에도 특정 요소가 준비될 때까지 기다리는 등의 여러 대기 방식이 있다.)

해당 코드를 넣었을 때 해당하는 생성자가 없다고 뜬다면, 버전이 일치하지 않아 생기는 문제니, 해당 버전에 맞는 방식으로 수정해야한다. 현재 작성된 Duration을 이용하는 방식은 4버전의 방식이다.

 

실행해보면,

(동적데이터라 크롤링한 데이터가 계속해서 변경되는 것을 확인할 수 있다.)

 

상단의 셀레니움이 실행되며 나오는 로그가 뜨고, 크롤링한 데이터가 출력되는 것을 확인할 수 있다.

중간중간 비어있는 요소는 해당 페이지에서 빈 내용을 가진 strong.tit_g가 있는 것으로 보여진다.

 

지금은 바로 뜨는 페이지만 크롤링해서 왔지만, 셀레니움은 다양한 기능을 통해 로그인하거나, 클릭하거나, 검색을 해 크롤링 시킬 수 있는 다양한 기능을 가지고 있다.

 

Selenium 4에서 Java로 자주 사용되는 기능

기능 메서드 설명
클릭 element.click(); 웹 요소를 클릭한다.
텍스트 입력 element.sendKeys("text"); 텍스트 입력란에 텍스트를 입력한다.
텍스트 지우기 element.clear(); 입력란에 이미 입력된 텍스트를 지운다.
요소 찾기 driver.findElement(By.by()); 특정 요소를 찾는다.
여러 요소 찾기 driver.findElements(By.by()); 특정 요소들의 리스트를 찾는다.
드래그 앤 드롭 actions.dragAndDrop(src, target).perform(); 요소를 드래그 앤 드롭한다.
더블 클릭 actions.doubleClick(element).perform(); 요소를 더블 클릭한다.
마우스 오버 actions.moveToElement(element).perform(); 마우스를 요소 위로 이동한다.
스크롤 ((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView(true);", element); 페이지를 특정 요소로 스크롤한다.
키보드 입력 element.sendKeys(Keys.RETURN); 키보드 입력을 시뮬레이션한다.
키보드 단축키 element.sendKeys(Keys.chord(Keys.CONTROL, "a")); 특정 키보드 단축키를 누흔다.
프레임 전환 driver.switchTo().frame(index); 특정 인덱스의 프레임으로 전환한다.
팝업 창 전환 driver.switchTo().window(windowHandle); 특정 창으로 전환한다.
페이지 새로고침 driver.navigate().refresh(); 현재 페이지를 새로고침한다.
페이지 이동 driver.navigate().to("http://url.com"); 특정 URL로 이동한다.
뒤로 가기 driver.navigate().back(); 브라우저에서 뒤로 간다.
앞으로 가기 driver.navigate().forward(); 브라우저에서 앞으로 간다.
스크린샷 찍기 File screenshot = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE); 현재 페이지의 스크린샷을 찍는다.
알림 창 처리 driver.switchTo().alert(); 현재 활성화된 알림 창을 처리한다.

 

 

사용 예시

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.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.JavascriptExecutor;
import java.io.File;
import org.apache.commons.io.FileUtils;

public class SeleniumExample {
    public static void main(String[] args) {
 		//WebDriverManager를 통해 버전 관리를 용이하게 하는 방법
 		WebDriverManager.chromedriver().setup();


        // WebDriver 객체 생성
        WebDriver driver = new ChromeDriver();

        try {
            // 웹 페이지 열기
            driver.get("사이트 주소");

            // 요소 찾기 - 예를 들어, 버튼 클릭
            WebElement button = driver.findElement(By.id("button-id"));
            button.click();

            // 텍스트 입력란에 텍스트 입력
            WebElement inputField = driver.findElement(By.id("input-field-id"));
            inputField.sendKeys("텍스트입력");

            // 텍스트 지우기
            inputField.clear();

            // 다시 텍스트 입력
            inputField.sendKeys("다시 텍스트 입력");

            // 마우스 오버
            Actions actions = new Actions(driver);
            WebElement menu = driver.findElement(By.id("요소"));
            actions.moveToElement(menu).perform();

            // 스크롤
            WebElement elementToScroll = driver.findElement(By.id("요소"));
            ((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView(true);", elementToScroll);

            // 스크린샷 찍기
            File screenshot = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
            FileUtils.copyFile(screenshot, new File("파일.png"));

            // 입력된 텍스트를 콘솔에 출력
            String enteredText = inputField.getAttribute("value");
            System.out.println("입력된 텍스트: " + enteredText);

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 브라우저 닫기
            driver.quit();
        }
    }
}

 

 

 

[참고용/셀레니움3과 4 비교] https://m.blog.naver.com/swimmingsdesign/223034723268

[참고용/옛날 버전 셀레니움 / 수동 연결드라이버] https://sw-test.tistory.com/2

[참고용/WebDriverManager] https://mag1c.tistory.com/383