웹 스크래핑을 위한 탐지되지 않는 ChromeDriver 사용 방법

Undetected ChromeDriver가 웹 스크래핑을 위한 안티봇 시스템을 우회하는 방법을 알아보고, 단계별 가이드, 고급 기법 및 주요 제한 사항을 확인하세요.
3 분 읽기
Undetected ChromeDriver for Web Scraping

이 가이드에서는 다음을 배울 수 있습니다:

  • Undetected ChromeDriver란 무엇이며 어떻게 유용한지
  • 봇 탐지를 최소화하는 방법
  • 웹 스크래핑을 위해 Python과 함께 사용하는 방법
  • 고급 활용법 및 기법
  • 주요 한계점과 단점
  • 유사 기술

자, 시작해 보겠습니다!

Undetected ChromeDriver란 무엇인가요?

Undetected ChromeDriver는Selenium의 ChromeDriver를 최적화한 버전을 제공하는 Python 라이브러리입니다. 이 라이브러리는 다음과 같은 봇 방지 서비스의 탐지를 제한하기 위해 패치되었습니다:

  • Imperva
  • DataDome
  • 디스틸 네트워크스

또한 특정 Cloudflare 보호 기능을 우회하는 데도 도움이 될 수 있지만, 이는 더 어려울 수 있습니다. 자세한 내용은Cloudflare 우회 방법 가이드를 참조하세요.

Selenium과 같은브라우저 자동화 도구를사용해 본 적이 있다면, 이를 통해 브라우저를 프로그래밍 방식으로 제어할 수 있다는 것을 알 것입니다. 이를 가능하게 하기 위해, 이러한 도구들은 일반 사용자 설정과 다르게 브라우저를 구성합니다.

안티봇 시스템은 자동화된 브라우저 봇을 식별하기 위해 이러한 차이점, 즉 “누출”을 찾습니다. Undetected ChromeDriver는 이러한 흔적을 최소화하기 위해 Chrome 드라이버를 패치하여 봇 탐지를 줄입니다. 따라서안티 스크래핑 조치로 보호되는 웹 스크래핑 사이트에 이상적입니다!

작동 원리

Undetected ChromeDriver는 다음과 같은 기법을 활용하여 Cloudflare, Imperva, DataDome 및 유사 솔루션의 탐지를 줄입니다:

  • 실제 브라우저에서 사용하는 것과 유사하게 셀레니움 변수 이름 변경
  • 탐지를 피하기 위해 합법적이고 실제 사용되는 User-Agent 문자열 사용
  • 사용자가 자연스러운 인간 상호작용을 시뮬레이션할 수 있도록 지원
  • 웹사이트 탐색 시 쿠키 및 세션의 적절한 관리
  • IP 차단을 우회하고 속도 제한을 방지하기 위한 프록시 사용 지원

이러한 방법을 통해 라이브러리가 제어하는 브라우저는 다양한 스크래핑 방지 방어를 효과적으로 우회할 수 있습니다.

웹 스크래핑을 위한 탐지되지 않는 ChromeDriver 사용: 단계별 가이드

대부분의 사이트는 자동화된 스크립트가 페이지에 접근하는 것을 차단하기 위해 고급 봇 방지 조치를 사용합니다. 이러한 메커니즘은웹 스크래핑 봇도효과적으로 차단합니다.

예를 들어, 다음GoDaddy 제품 페이지에서 제목과 설명을 스크래핑한다고 가정해 보겠습니다:

The GoDaddy target page

Python의 기본 Selenium을 사용하면 스크래핑 스크립트는 다음과 같을 것입니다:

# pip install selenium

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By

# 헤드리스 모드로 시작하도록 Chrome 인스턴스 구성
options = Options()
options.add_argument("--headless")

# Chrome 웹 드라이버 인스턴스 생성
driver = webdriver.Chrome(service=Service(), options=options)

# 대상 페이지에 연결
driver.get("https://www.godaddy.com/hosting/wordpress-hosting")

# 스크래핑 로직...

# 브라우저 종료
driver.quit()

이 로직이 익숙하지 않다면Selenium 웹 스크래핑 가이드를 참고하세요.

스크립트를 실행하면 다음과 같은 오류 페이지로 인해 실패합니다:

An "Access Denied" page from GoDaddy

즉, Selenium 스크립트가 봇 방지 솔루션(이 예시에서는 Akamai)에 의해 차단된 것입니다.

그렇다면 이를 어떻게 해결할 수 있을까요? 해답은 Undetected ChromeDriver입니다!

웹 스크래핑을 위해 undetected_chromedriver Python 라이브러리를 사용하는 방법을 알아보려면 아래 단계를 따르세요.

1단계: 필수 조건 및 프로젝트 설정

Undetected ChromeDriver는 다음 전제 조건이 필요합니다:

참고: 라이브러리가 자동으로 드라이버 바이너리를 다운로드하고 패치하므로ChromeDriver를 수동으로 다운로드할 필요가 없습니다.

이제 다음 명령어를 사용하여 프로젝트 디렉터리를 생성하세요:

mkdir undetected-chromedriver-scraper

undetected-chromedriver-scraper 디렉터리는 Python 스크레이퍼의 프로젝트 폴더 역할을 합니다.

해당 디렉터리로 이동하여가상 환경을 초기화하세요:

cd undetected-chromedriver-scraper
python -m venv env

선호하는 Python IDE로 프로젝트 폴더를 엽니다.Python 확장 프로그램이 설치된 Visual Studio Code나PyCharm Community Edition이모두 훌륭한 선택입니다.

다음으로 프로젝트 폴더 내에 아래 구조를 따라scraper.py파일을 생성하세요:

scraper.py in the project folder

현재scraper.py는빈 Python 스크립트입니다. 곧 여기에 스크래핑 로직을 추가하게 됩니다.

IDE 터미널에서 가상 환경을 활성화하세요. Linux 또는 macOS에서는 다음 명령어를 사용합니다:

./env/bin/activate

Windows에서는 동일하게 다음 명령을 실행하세요:

env/Scripts/activate

훌륭합니다! 이제 브라우저 자동화를 통한 웹 스크래핑을 위한 Python 환경이 준비되었습니다.

2단계: Undetected ChromeDriver 설치

활성화된 가상 환경에서undetected_chromedriverpip 패키지를 통해 Undetected ChromeDriver를 설치하세요:

pip install undetected_chromedriver 

이 라이브러리는 의존성 중 하나인 Selenium을 자동으로 설치합니다. 따라서 Selenium을 별도로 설치할 필요가 없습니다. 이는 기본적으로 모든 Selenium 임포트에 접근할 수 있음을 의미합니다.

단계 #3: 초기 설정

undetected_chromedriver 임포트:

import undetected_chromedriver as uc

그런 다음 Chrome WebDriver를 다음과 같이 초기화할 수 있습니다:

driver = uc.Chrome()

Selenium과 마찬가지로, 이 드라이버는 Selenium API를 사용하여 제어할 수 있는 브라우저 창을 엽니다. 즉, 드라이버 객체는 모든 표준 Selenium 메서드와 함께 나중에 살펴볼 몇 가지 추가 기능을 제공합니다.

핵심 차이점은 이 Chrome 드라이버 버전이 특정 봇 방지 솔루션을 우회하도록 패치되었다는 점입니다.

드라이버를 종료하려면 quit() 메서드를 호출하면 됩니다:

driver.quit() 

기본적인 Undetected ChromeDriver 설정 예시는 다음과 같습니다:

import undetected_chromedriver as uc

# Chrome 인스턴스 초기화
driver = uc.Chrome()

# 스크래핑 로직...

# 브라우저 닫기 및 리소스 해제
driver.quit()

훌륭합니다! 이제 브라우저에서 직접 웹 스크래핑을 수행할 준비가 되었습니다.

4단계: 웹 스크래핑에 활용하기

경고: 이 섹션은 표준 Selenium 설정과 동일한 단계를 따릅니다. Selenium 웹 스크래핑에 이미 익숙하다면, 최종 코드가 있는 다음 섹션으로 건너뛰어도 됩니다.

먼저 get() 메서드를 사용하여 브라우저를 대상 페이지로 이동시킵니다:

driver.get("https://www.godaddy.com/hosting/wordpress-hosting")

다음으로, 브라우저의 시크릿 모드에서 해당 페이지를 방문하고 스크래핑할 요소를 검사합니다:

The DevTools inspection of the HTML elements to scrape data with

제품 제목, 태그라인, 설명을 추출한다고 가정합니다.

다음 코드로 이 모든 정보를 스크래핑할 수 있습니다:

headline_element = driver.find_element(By.CSS_SELECTOR, "[data-cy="headline"]")

title_element = headline_element.find_element(By.CSS_SELECTOR, "h1")
title = title_element.text

tagline_element = headline_element.find_element(By.CSS_SELECTOR, "h2")
tagline = tagline_element.text

description_element = headline_element.find_element(By.CSS_SELECTOR, "[data-cy="description"]")
description = description_element.text

위 코드가 작동하려면 Selenium에서 By를 임포트해야 합니다:

from selenium.webdriver.common.by import By

이제 스크랩한 데이터를 Python 사전(dictionary)에 저장합니다:

product = {
  "title": title,
  "tagline": tagline,
  "description": description
}

마지막으로 데이터를 JSON 파일로 내보냅니다:

with open("product.json", "w") as json_file:
  json.dump(product, json_file, indent=4)

파이썬 표준 라이브러리에서 json을 임포트하는 것을 잊지 마세요:

import json

자, 이제 끝났습니다! 기본적인 Undetected ChromeDriver 웹 스크래핑 로직을 구현하셨습니다.

5단계: 모든 것을 통합하기

다음은 최종 스크래핑 스크립트입니다:

import undetected_chromedriver as uc
from selenium.webdriver.common.by import By
import json

# Chrome 웹 드라이버 인스턴스 생성
driver = uc.Chrome()

# 대상 페이지에 연결
driver.get("https://www.godaddy.com/hosting/wordpress-hosting")

# 스크래핑 로직
headline_element = driver.find_element(By.CSS_SELECTOR, "[data-cy="headline"]")

title_element = headline_element.find_element(By.CSS_SELECTOR, "h1")
title = title_element.text

tagline_element = headline_element.find_element(By.CSS_SELECTOR, "h2")
tagline = tagline_element.text

description_element = headline_element.find_element(By.CSS_SELECTOR, "[data-cy="description"]")
description = description_element.text

# 스크랩한 데이터로 사전 채우기
product = {
  "title": title,
  "tagline": tagline,
  "description": description
}

# 스크랩한 데이터를 JSON으로 내보내기
with open("product.json", "w") as json_file:
  json.dump(product, json_file, indent=4)

# 브라우저를 닫고 리소스를 해제
driver.quit() 

다음 명령어로 실행:

python3 scraper.py

또는 Windows에서:

python scraper.py

이 명령어는 기본 Selenium과 달리 오류 페이지가 아닌 대상 웹 페이지를 표시하는 브라우저를 엽니다:

a browser showing the target web page

스크립트는 페이지에서 데이터를 추출하여 다음과 같은 product.json 파일을 생성합니다:

{
    "title": "관리형 WordPress 호스팅",
    "tagline": "간편해진 WordPress 호스팅",
    "description": "WordPress 사이트 생성, 출시 및 관리를 더 쉽게 만들어 드립니다"
}

undetected_chromedriver: 고급 사용법

이제 라이브러리 작동 방식을 이해했으니, 더 고급 시나리오를 탐색할 준비가 되었습니다.

특정 Chrome 버전 선택

version_main 인수를 설정하여 라이브러리가 사용할 특정 Chrome 버전을 지정할 수 있습니다:

import undetected_chromedriver as uc

# 대상 Chrome 버전 지정
driver = uc.Chrome(version_main=105)

참고: 이 라이브러리는 다른 크로미움 기반 브라우저에서도 작동하지만, 추가적인 설정이 필요합니다.

with 구문 사용

더 이상 드라이버가 필요하지 않을 때quit()메서드를 수동으로 호출하지 않으려면 아래와 같이with구문을 사용할 수 있습니다:

import undetected_chromedriver as uc

with uc.Chrome() as driver:
    driver.get("<YOUR_URL>")

with 블록 내부의 코드가 완료되면 Python이 자동으로 브라우저를 종료합니다.

참고: 이 구문은 버전 3.1.0부터 지원됩니다.

프록시 통합

Undetected ChromeDriver에 프록시를 추가하는 구문은 일반 Selenium과 유사합니다. 아래와 같이 프록시 URL을 --proxy-server 플래그에 전달하기만 하면 됩니다:

import undetected_chromedriver as uc

proxy_url = "<YOUR_PROXY_URL>"

options = uc.ChromeOptions()
options.add_argument(f"--proxy-server={proxy}")

참고: Chrome은 --proxy-server 플래그를 통한 인증 프록시를 지원하지 않습니다.

확장 API

undetected_chromedriver는 일반적인 Selenium 기능을 다음과 같은 몇 가지 메서드로 확장합니다:

  • WebElement.click_safe(): 링크 클릭 시 탐지가 발생하는 경우 이 메서드를 사용하세요. 작동이 보장되지는 않지만, 더 안전한 클릭을 위한 대안 접근법을 제공합니다.
  • WebElement.children(tag=None, recursive=False): 자식 요소를 쉽게 찾을 수 있도록 도와줍니다. 예시:
# body 내 모든 태그의 6번째 자식 요소를 가져온 후, 재귀적으로 모든 <img> 요소를 찾음
images = body.children()[6].children("img", True)

undetected_chromedriver Python 라이브러리의 한계점

undetected_chromedriver는 강력한 Python 라이브러리이지만 알려진 몇 가지 한계가 있습니다. 반드시 알아야 할 가장 중요한 사항들은 다음과 같습니다!

IP 차단

라이브러리의 GitHub 페이지에 명시된 바와 같이:이 패키지는 사용자의 IP 주소를 숨기지 않습니다. 따라서 데이터센터에서 스크립트를 실행하는 경우 탐지될 가능성이 높습니다. 마찬가지로 가정용 IP의 평판이 좋지 않은 경우에도 차단될 수 있습니다!

The warning about IP blocks on GitHub

IP를 숨기려면 앞서 시연한 바와 같이 제어되는 브라우저를 프록시 서버와 통합해야 합니다.

GUI 탐색 미지원

모듈의 내부 작동 방식 때문에 get() 메서드를 사용해 프로그래밍 방식으로 탐색해야 합니다. 키보드나 마우스로 페이지와 상호작용하는 수동 탐색을 위해 브라우저 GUI를 사용하지 마세요—탐지 위험이 높아집니다!

새 탭 처리에도 동일한 규칙이 적용됩니다. 여러 탭을 사용해야 할 경우, 드라이버가 허용하는 URL 데이터: ( 쉼표 포함)를 사용하여 빈 페이지의 새 탭을 엽니다. 이후 평소와 같은 자동화 로직을 진행하세요.

이러한 지침을 준수해야만 탐지를 최소화하고 더 원활한 웹 스크래핑 세션을 즐길 수 있습니다.

헤드리스 모드에 대한 제한된 지원

공식적으로 undetected_chromedriver 라이브러리는 헤드리스 모드를 완전히 지원하지 않습니다. 다만 다음 구문을 사용하여 실험해 볼 수 있습니다:

driver = uc.Chrome(headless=True)

개발자는 버전 3.4.5 변경 로그에서 헤드리스 모드가 작동하며 봇 우회 기능을 보장한다고 발표했습니다. 그러나 여전히 불안정합니다. 이 기능을 신중하게 사용하고 스크래핑 요구 사항을 충족하는지 철저히 테스트하십시오.

안정성 문제

패키지의 PyPI 페이지에 명시된 바와 같이, 다양한 요인으로 인해 결과가 달라질 수 있습니다. 탐지 알고리즘을 이해하고 대응하기 위한 지속적인 노력 외에는 어떠한 보장도 제공되지 않습니다.

The alert about unpredictable results on PyPI

이는 Distil, Cloudflare, Imperva, DataDome 또는 hCaptcha를 오늘 성공적으로 우회한 스크립트가 내일 반봇 솔루션이 업데이트되면 실패할 수 있음을 의미합니다:

A CAPTCHA trigger by Undetected ChromeDriver

위 이미지는 공식 문서에 제공된 스크립트의 결과입니다. 이는 해당 도구의 개발자가 만든 스크립트조차 항상 예상대로 작동하지 않을 수 있음을 보여줍니다. 구체적으로, 이 스크립트는 CAPTCHA를 트리거하여 자동화 로직을 쉽게 중단시킬 수 있습니다.

Python에서 CAPTCHA 우회 방법에 대한 가이드에서 자세히 알아보세요.

추가 자료

탐지되지 않는 ChromeDriver는 탐지를 방지하기 위해 브라우저 드라이버를 수정하는 유일한 라이브러리가 아닙니다. 유사한 도구를 탐색하거나 이 주제에 대해 더 알고 싶다면 다음 가이드를 읽어보세요:

결론

이 글에서는 Undetected ChromeDriver를 사용해 Selenium에서 봇 탐지를 처리하는 방법을 알아보았습니다. 이 라이브러리는 차단되지 않고 웹 스크래핑을 수행할 수 있도록 수정된 ChromeDriver 버전을 제공합니다.

문제는 Cloudflare와 같은 고급 봇 방지 기술이 여전히 여러분의 스크립트를 탐지하고 차단할 수 있다는 점입니다. undetected_chromedriver와 같은 라이브러리는 불안정합니다—오늘은 작동할 수 있지만 내일은 작동하지 않을 수도 있습니다.

문제는 브라우저를 제어하는 Selenium의 API에 있는 것이 아니라 브라우저 설정 자체에 있습니다. 이는 해결책이 클라우드 기반의 항상 업데이트되고 확장 가능한 브라우저이며, 내장된 봇 방지 우회 기능을 갖추어야 함을 의미합니다. 그런 브라우저가 존재하며,바로 Scraping Browser입니다!

Bright Data의 Scraping Browser는Selenium,Puppeteer,Playwright 등과 호환되는 고도로 확장 가능한 클라우드 브라우저입니다. 브라우저 지문 인식, CAPTCHA 해결, 자동 재시도를 처리해 줍니다. 또한 요청마다 출구 IP를 자동으로 회전시킵니다. 이는 다음과 같은 전 세계 프록시 네트워크 덕분에 가능합니다:

지금 바로 무료 Bright Data 계정을 생성하여 스크래핑 브라우저를 체험하거나 프록시를 테스트해 보세요.