[Spring Boot] Java로 웹 크롤링 하기 - Selenium
지난번 포스팅에서는 Spring Boot 환경에서 웹 크롤링을 하기 위해
Java 라이브러리인 Jsoup을 어떻게 적용하고, 사용하는지에 대해 확인하면서
정적인 페이지만 크롤링 가능하다는 점을 알게 되었다. (Jsoup은 동적 페이지는 크롤링을 하지 못한다.)
이를 해결하기 위해 또 다른 크롤링 라이브러리인 셀레니움(Selenium)에 대해 알아보려고 한다.
공식 홈페이지에 따르면 웹 브라우저의 자동화를 가능하게 하고
다양한 도구와 라이브러리를 지원하는 프로젝트라고 되어 있다.
바로 시작해보자😉
Selenium 라이브러리 적용 및 사용하기
1. 예제 살펴보기
Selenium 공식 홈페이지에서 document를 보면 소스 코드는 무료로 이용이 가능하고 여러 언어들을 지원하고 있다.
우리는 크롬을 이용하여 크롤링하고, 언어는 Java를 사용하기 때문에 여러 언어들 중에서 Java 예제를 살펴보자.
package dev.selenium.hello;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
public class HelloSelenium {
public static void main(String[] args) {
WebDriver driver = new ChromeDriver();
driver.get("https://selenium.dev");
driver.quit();
}
}
위 소스를 보면 웹 드라이버 인터페이스를 통해 크롬 드라이버를 사용해서 크롤링하려는 페이지에 접속하고 있다.
Jsoup과 비교하더라도 사용방법은 간단한 것 같다.
다른 점은 드라이버를 따로 설치해야 한다는 점?
2. 크롬 드라이버 (Chrome Driver)
셀레니움을 사용하기 위해서는 크롬(Chrome)과 크롬 드라이버(Chrome Driver)를 설치해야 한다.
개발하려는 환경의 크롬이 설치되어 있지 않다면 크롬과 드라이버를 설치하자.
설치할 때 주의사항으로는 크롬과 드라이버의 버전이 동일해야 한다.
현재 사용 중인 크롬의 버전 정보 확인하는 방법은
크롬 설정 > Chrome 정보 탭에서 확인이 가능하다.
3. 라이브러리 추가하기 (Gradle, Maven)
Gradle, Maven 빌드 방법에 따라 다음과 같이 라이브러리 dependency를 추가한다.
- Gradle (build.gradle)
implementation 'org.seleniumhq.selenium:selenium-java:4.6.0'
- Maven (pom.xml)
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>4.6.0</version>
</dependency>
4. 셀레니움(Selenium) 사용하기
WebDriverUtil 클래스를 통해 크롬 드라이버를 생성하고 크롬옵션(ChromeOptions)을 설정하도록 했고,
크롬 드라이버의 설치 경로를 담은 WEB_DRIVER_PATH 상수를 만들었다.
ex) C:/test/webdriver/chromedriver.exe
package com.deepit.batch.core.util;
import java.time.Duration;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
@Component
public class WebDriverUtil {
private static String WEB_DRIVER_PATH; // WebDriver 경로
public static WebDriver getChromeDriver() {
if (ObjectUtils.isEmpty(System.getProperty("webdriver.chrome.driver"))) {
System.setProperty("webdriver.chrome.driver", WEB_DRIVER_PATH);
}
// webDriver 옵션 설정
ChromeOptions chromeOptions = new ChromeOptions();
chromeOptions.setHeadless(true);
chromeOptions.addArguments("--lang=ko");
chromeOptions.addArguments("--no-sandbox");
chromeOptions.addArguments("--disable-dev-shm-usage");
chromeOptions.addArguments("--disable-gpu");
chromeOptions.setCapability("ignoreProtectedModeSettings", true);
WebDriver driver = new ChromeDriver(chromeOptions);
driver.manage().timeouts().pageLoadTimeout(Duration.ofSeconds(30));
return driver;
}
@Value("#{resource['driver.chrome.driver_path']}")
public void initDriver(String path) {
WEB_DRIVER_PATH = path;
}
public static void quit(WebDriver driver) {
if (!ObjectUtils.isEmpty(driver)) {
driver.quit();
}
}
public static void close(WebDriver driver) {
if (!ObjectUtils.isEmpty(driver)) {
driver.close();
}
}
}
해당 소스에서는 드라이버 파일경로를 resource.properties 파일에 정의하여 가져오도록 했지만
그냥 상수에 값을 직접 넣어줘도 된다.
위에서 만든 WebDriverUtil 클래스를 사용해서 드라이버를 생성하고
크롤링하고자 하는 url과 특정 태그의 id나 class 등의 선택자를 입력한다.
implicitlyWait(페이지 전체가 넘어오기까지 대기) 메소드를 사용해서 통해 대기시간을 지정한다.
WebDriver driver = WebDriverUtil.getChromeDriver();
List<WebElement> webElementList = new ArrayList<>();
String url = "http://test";
String query = "#id";
if (!ObjectUtils.isEmpty(driver)) {
driver.get(url);
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(5));
webElementList = driver.findElements(By.cssSelector(query));
}
이제 크롤링해온 데이터를 가지고 내가 원하는 데이터들을 뽑거나
혹은 클릭(click)이나 전송(submit) 같은 동작도 수행할 수 있다.
WebElement parentElement = webElementList.get(0);
List<WebElement> childElement = parentElement.findElements(By.tagName("td"));
System.out.println(childElement.get(0).getText());
System.out.println(parentElement.getAttribute("class"));
System.out.println(parentElement.getCssValue("height"));
parentElement.click();
parentElement.submit();
태그명, 클래스명, CSS선택자 등을 By를 통해 Element를 찾을 수도 있고
찾은 element의 속성, 클래스, CSS 등의 정보들도 알 수 있으며, 자식 element까지 접근이 가능하다.
게다가 click과 submit 같은 이벤트도 호출이 가능하다.
5. 주의할 점
위에서도 언급했지만 크롬과 크롬 드라이버 설치할 때, 크롬과 드라이버의 버전이 동일해야 하는데
크롬이 자동으로 업데이트가 되면서 버전이 변경되어 버린다면 셀레니움 크롤링이 동작하지 않을 수 있다.
크롬이 자동으로 업데이트되지 않도록 해주면 해결된다. (구글링 하면 금방 따라 할 수 있으니 찾아보길 권한다.)
버전관리만 주의해주면 유용하면서 사용하기 쉬운 라이브러리라고 생각된다.
Jsoup을 사용하는 데 있어 동적 페이지는 크롤링이 되지 않는 문제 때문에 셀레니움(Selenium)을 사용하게 되었다.
덕분에 동적 페이지도 정상적으로 크롤링에 성공했고 나중에 클릭 및 전송 이벤트가 필요한 경우가 생긴다면 유용하게 사용할 수 있다.
해당 글에서는 라이브러리 기능들이나 소스 설명은 생략했고
라이브러리 적용 및 사용에 초점을 두고 작성하였으며
자세한 각 기능들 사용방법은 공식문서를 참고하면 된다.
두 라이브러리 모두 사용하기 쉬웠고,
동적인 페이지 크롤링이 필요하다면 셀레니움을
정적인 페이지만 크롤링한다면 Jsoup을 사용하면 될 것 같다.
'사이드 프로젝트 > 크롤링' 카테고리의 다른 글
[Spring Boot] Java로 웹 크롤링 하기 - Jsoup (0) | 2023.01.02 |
---|