JAVA

[JAVA] JSoup AJAX와 동적 페이지 처리

인생아 2024. 10. 29. 11:25
반응형

웹에서 AJAX(Asynchronous JavaScript and XML) 요청이 이루어지는 동적 페이지는 일반적인 정적 HTML 페이지와는 다르게 JavaScript로 데이터를 로딩하거나 갱신합니다. JSoup은 기본적으로 정적인 HTML 페이지를 처리하는 데 적합하므로, 동적 데이터를 다루기 위해서는 다른 도구들과 결합해 사용하는 것이 효과적입니다. 이 글에서는 AJAX 요청 처리 개념과 동적 콘텐츠 수집 방법, 그리고 Selenium과 JSoup을 함께 사용하는 방법을 다뤄보겠습니다.

AJAX 요청 처리 개념 이해하기

AJAX는 페이지 전체를 새로 고치지 않고 필요한 데이터만 서버에서 받아와 비동기 방식으로 화면에 표시합니다. 이런 방식으로 웹 애플리케이션의 응답 속도가 빨라지고, 사용자 경험도 개선됩니다. 그러나 AJAX로 데이터를 가져오는 웹 페이지는 브라우저에서 JavaScript가 실행된 후에야 데이터가 로드되기 때문에, 일반적인 HTML 파싱 방식으로는 데이터를 수집하기 어렵습니다.

AJAX 요청을 통해 데이터를 가져오는 기본 원리는 XMLHttpRequest 또는 fetch 함수를 이용하여 서버와 비동기적으로 통신하는 것입니다. 예를 들어, 아래 JavaScript 코드처럼 fetch API를 이용해 데이터를 가져오는 경우를 볼 수 있습니다.

fetch('https://example.com/data')
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error('Error fetching data:', error));

이 코드는 브라우저 콘솔에서 AJAX 요청을 통해 JSON 데이터를 받아오는 방식입니다. 서버에서 응답한 JSON 데이터를 비동기적으로 받아 처리하는 로직입니다.

동적 콘텐츠의 데이터 수집 방법

AJAX로 로드되는 데이터를 수집하려면 JavaScript를 직접 실행해 AJAX 요청을 완성한 후 데이터를 받아와야 합니다. 이 경우 JSoup만으로는 한계가 있기 때문에, 아래와 같은 다양한 방법을 활용할 수 있습니다.

1. AJAX 요청 경로 추출하여 별도 요청
개발자 도구의 네트워크 탭을 통해 AJAX 요청을 추적해, 해당 요청 URL을 통해 직접 데이터를 가져오는 방법입니다. 네트워크 탭을 열고 데이터를 로드할 때 요청된 XHR(XMLHttpRequest)을 확인하여 요청 URL을 복사할 수 있습니다. 아래 예시는 이 방식으로 JSON 데이터를 가져오는 코드입니다.

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import java.io.IOException;

public class AjaxRequestExample {
    public static void main(String[] args) {
        String url = "https://example.com/ajax/data";
        try {
            Document doc = Jsoup.connect(url)
                                .ignoreContentType(true)  // JSON을 HTML로 해석하지 않도록 설정
                                .get();
            System.out.println(doc.body().text());  // JSON 데이터 출력
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

ignoreContentType(true)는 JSON이나 XML 데이터를 HTML로 해석하지 않고 그대로 출력할 수 있도록 합니다. AJAX 요청을 추출해 직접 접근하는 방식은 빠르고 간편하지만, 모든 페이지에 적용되지는 않습니다. 특히 동적으로 자바스크립트를 렌더링하는 복잡한 경우라면 Selenium과 같은 브라우저 자동화 도구를 사용하는 것이 좋습니다.

2. JavaScript를 사용한 동적 데이터 처리: Selenium과 함께 사용하기

Selenium은 브라우저를 자동화하여 자바스크립트로 로드된 데이터를 렌더링 후 가져올 수 있는 도구입니다. Selenium을 사용하여 페이지를 로드하고 필요한 데이터가 로드될 때까지 기다린 후, JSoup을 이용해 DOM을 파싱하는 방식으로 동작할 수 있습니다.

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.By;

public class JsoupWithSeleniumExample {
    public static void main(String[] args) {
        // Selenium WebDriver 설정
        System.setProperty("webdriver.chrome.driver", "/path/to/chromedriver"); // Chromedriver 경로 설정
        WebDriver driver = new ChromeDriver();

        // 페이지 로드
        driver.get("https://example.com/dynamic-page");

        // 특정 요소가 로드될 때까지 대기
        WebElement element = driver.findElement(By.id("dynamic-content"));

        // 페이지 소스 가져오기
        String pageSource = driver.getPageSource();

        // JSoup을 사용하여 동적 콘텐츠 파싱
        Document doc = Jsoup.parse(pageSource);
        System.out.println(doc.select("div#dynamic-content").text());

        // 브라우저 종료
        driver.quit();
    }
}
 

이 예제는 Selenium WebDriver를 사용해 동적 페이지를 로드하고, 해당 페이지의 소스를 JSoup을 통해 분석하는 방식입니다. Selenium페이지 렌더링이 완료된 시점의 HTML을 가져오므로, 자바스크립트가 실행된 후의 데이터도 포함된 소스를 얻을 수 있습니다. 이 방식은 AJAX 기반의 동적 데이터를 수집하는 데 유용합니다.

Selenium과 함께 사용하는 방법 (JSoup + Selenium)

JSoup과 Selenium을 함께 사용하는 방식은 동적 페이지 처리에 매우 유용합니다. Selenium이 자바스크립트 렌더링을 담당하고, JSoup이 데이터를 추출하는 역할을 하기 때문에 두 도구의 조합을 통해 많은 정보를 효과적으로 수집할 수 있습니다. 특히 데이터가 자바스크립트로 렌더링되는 웹 페이지에서 사용자가 페이지의 특정 부분이 로드되기를 기다리게 할 수 있는 방법을 통해 데이터를 안정적으로 수집할 수 있습니다. 예를 들어, 페이지의 특정 요소가 나타날 때까지 기다린 후 데이터를 파싱하는 로직을 추가해 안정성을 높일 수 있습니다.

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

public class EnhancedJsoupSeleniumExample {
    public static void main(String[] args) {
        System.setProperty("webdriver.chrome.driver", "/path/to/chromedriver");

        WebDriver driver = new ChromeDriver();
        driver.get("https://example.com");

        WebDriverWait wait = new WebDriverWait(driver, 10);
        WebElement dynamicContent = wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("dynamic-content")));

        String pageSource = driver.getPageSource();
        Document doc = Jsoup.parse(pageSource);
        System.out.println(doc.select("#dynamic-content").text());

        driver.quit();
    }
}

참고사이트

반응형