티스토리 뷰
강력한 웹 자동화 도구, 셀레니움을 만나다
안녕하세요! 웹 자동화와 데이터 스크래핑에 관심을 가지고 계신 여러분을 위한 여정을 시작합니다. 반복적인 웹 작업에 지치셨거나 웹사이트에서 필요한 정보를 효율적으로 수집하고 싶으신가요? 코딩 경험이 많지 않은 입문자부터 업무 효율을 높이고 싶은 현직 개발자 및 QA 엔지니어에 이르기까지, 웹을 효과적으로 제어하고 자동화할 수 있도록 돕는 강력한 도구, 바로 셀레니움(Selenium)을 소개합니다.
"셀레니움이란 무엇인가요?" 셀레니움은 브라우저를 자동으로 움직이게 하는 소프트웨어입니다. 마치 우리가 마우스로 클릭하고 키보드로 입력하듯이, 셀레니움은 코드를 통해 실제 웹 브라우저를 조작하여 웹 페이지를 탐색하고, 데이터를 추출하며, 복잡한 테스트 시나리오까지 수행할 수 있게 해줍니다.
이 가이드는 단순히 셀레니움의 기능을 나열하는 것을 넘어, 여러분이 직접 셀레니움을 설치하고, 다양한 웹 자동화 예제를 통해 실전 감각을 익히며, 흔히 겪는 문제를 해결하는 방법까지 깊이 이해하고 활용할 수 있도록 돕습니다. 파이썬을 기반으로 한 실용적인 코드 예제와 초보자도 이해하기 쉬운 설명을 통해, 셀레니움이 여러분의 생산성을 극대화하는 든든한 조력자가 될 것입니다. 자, 그럼 셀레니움의 세계로 함께 뛰어들어 볼까요?

1. 셀레니움 웹 자동화, 왜 필수적일까?
현대 디지털 환경에서 웹 자동화의 중요성은 날마다 커지고 있습니다. 웹 기반 서비스의 폭발적인 증가로 인해, 수동으로 처리하기 어려운 반복적이고 지루한 작업들이 쌓여가고 있죠. 이때 등장하는 핵심 도구가 바로 셀레니움입니다.
1.1. 웹 자동화(Web Automation)란 무엇이며, 왜 필요한가요?
웹 자동화(Web Automation)는 컴퓨터 프로그램이 웹 브라우저 상의 일련의 동작을 자동으로 수행하도록 만드는 기술입니다. 웹 페이지 접속, 로그인, 버튼 클릭, 텍스트 입력, 데이터 검색, 파일 다운로드 등 우리가 브라우저에서 할 수 있는 대부분의 행위를 코드를 통해 구현할 수 있습니다.
웹 자동화가 필요한 주된 이유는 다음과 같습니다.
- 반복 작업의 효율화: 매일 반복되는 특정 웹사이트 방문, 정보 확인, 데이터 입력 등의 작업을 자동으로 처리하여 귀중한 시간을 절약할 수 있습니다.
- 인적 오류 방지: 수동 작업은 실수를 유발할 수 있지만, 자동화된 프로그램은 정해진 로직에 따라 정확하게 동작하므로 인적 오류를 최소화합니다.
- 처리 속도 향상: 사람이 직접 조작하는 것보다 코드로 명령을 내리는 것이 훨씬 빠릅니다. 대량의 데이터를 처리하거나 여러 작업을 동시에 수행할 때 엄청난 속도 향상을 가져옵니다.
- 접근성 및 확장성: 특정 웹사이트의 정보에 주기적으로 접근하거나, 웹 페이지의 변경 사항을 모니터링해야 할 때 자동화는 필수적입니다. 한 번 만든 스크립트는 필요에 따라 쉽게 수정하고 확장할 수 있습니다.
1.2. 셀레니움이 웹 자동화의 핵심 도구인 이유
수많은 웹 자동화 도구 중 셀레니움이 특별히 주목받는 이유는 다음과 같습니다.
- 실제 브라우저와의 상호작용: 셀레니움은 크롬, 파이어폭스, 엣지 등 실제 웹 브라우저를 직접 실행하여 웹 페이지와 상호작용합니다. 이는 웹 페이지의 복잡한 JavaScript 코드나 동적으로 로딩되는 콘텐츠까지 완벽하게 처리할 수 있다는 의미입니다. 마치 '가상 사용자'가 직접 브라우저를 조작하는 것과 같습니다.
- 다양한 프로그래밍 언어 지원: 파이썬은 물론, 자바, C#, 루비, 자바스크립트 등 다양한 프로그래밍 언어를 지원하여 사용자가 익숙한 언어로 자동화 스크립트를 작성할 수 있습니다. 특히 파이썬은 문법이 간결하고 라이브러리가 풍부하여 셀레니움을 배우는 데 최적의 언어로 손꼽힙니다.
- 강력한 커뮤니티와 자료: 전 세계적으로 많은 개발자와 사용자들이 셀레니움을 활용하며, 풍부한 문서, 튜토리얼, 그리고 활발한 커뮤니티가 형성되어 있습니다. 문제 발생 시 해결책을 찾기 용이하며, 지속적인 업데이트를 통해 기능이 개선됩니다.
- 다목적 활용: 셀레니움은 단순히 웹 테스트 자동화 도구를 넘어, 웹 스크래핑(Web Scraping, 웹 데이터 추출), 리포트 자동 생성, 반복적인 데이터 입력 작업 자동화, 온라인 마케팅 도구 등 무궁무진한 분야에서 활용될 수 있습니다.
셀레니움은 웹 페이지를 이해하고 제어하는 데 필요한 강력한 기능과 유연성을 제공하며, 실제 사용자 경험에 가까운 자동화를 구현할 수 있게 해줍니다. 이러한 특징 덕분에 "셀레니움 웹 자동화"는 오늘날 많은 기업과 개인에게 필수적인 기술이 되고 있습니다. 코딩 경험이 많지 않더라도 걱정할 필요 없습니다. 차근차근 따라오시면 셀레니움을 능숙하게 활용할 수 있을 것입니다.
2. 셀레니움 개발 환경 구축: 파이썬으로 5분 만에 시작하기
셀레니움을 본격적으로 활용하기 전에, 컴퓨터에 필요한 도구들을 설치하고 기본적인 환경을 구축해야 합니다. 복잡하게 들릴 수 있지만, 파이썬과 함께라면 "셀레니움 설치 방법"은 놀랍도록 간단합니다. 지금부터 초보자도 쉽게 따라 할 수 있도록 단계별로 설명해 드리겠습니다.
2.1. 사전 준비: 파이썬 설치 확인
셀레니움은 파이썬과 함께 사용될 때 가장 강력하고 배우기 쉽습니다. 만약 아직 파이썬이 설치되어 있지 않다면, 먼저 파이썬 공식 웹사이트(https://www.python.org/downloads/)에서 최신 버전을 다운로드하여 설치해 주세요. 설치 시 'Add Python to PATH' 옵션을 반드시 체크하는 것을 잊지 마세요. 이 옵션은 파이썬 명령어를 터미널(명령 프롬프트/PowerShell)에서 바로 실행할 수 있게 해줍니다.
파이썬 설치가 완료되었다면, 터미널(Windows: cmd 또는 PowerShell, macOS/Linux: Terminal)을 열고 다음 명령어를 입력하여 파이썬이 올바르게 설치되었는지 확인합니다.
python --version
# 또는
python3 --version
버전 정보(예: Python 3.9.7)가 출력된다면 성공입니다.
2.2. 셀레니움 라이브러리 설치
이제 셀레니움을 파이썬 프로젝트에서 사용할 수 있도록 라이브러리를 설치할 차례입니다. 파이썬의 패키지 관리 도구인 pip를 이용하여 아주 간단하게 설치할 수 있습니다.
터미널에 다음 명령어를 입력하고 실행하세요.
pip install selenium
# 또는
pip3 install selenium
설치가 완료되면, 셀레니움이 여러분의 파이썬 환경에 성공적으로 추가된 것입니다.
2.3. 웹 드라이버(WebDriver) 설치 및 설정
셀레니움은 실제 브라우저를 제어합니다. 이때, 셀레니움 코드와 실제 브라우저(크롬, 파이어폭스 등) 간의 통신을 담당하는 '다리' 역할을 하는 것이 바로 웹 드라이버(WebDriver)입니다. 사용하는 브라우저 종류에 따라 해당하는 웹 드라이버를 설치해야 합니다. 여기서는 가장 많이 사용되는 크롬(Chrome) 브라우저를 예시로 설명하겠습니다.
가장 권장되는 방법은 WebDriverManager를 사용하여 자동으로 드라이버를 관리하는 것입니다.
webdriver-manager라이브러리 설치:
터미널에 다음 명령어를 입력하고 실행합니다.이 라이브러리는 현재 설치된 크롬 브라우저 버전에 맞는 ChromeDriver를 자동으로 찾아 다운로드하고 설정해줍니다.pip install webdriver-manager- 수동 설치 (필요시):
만약WebDriverManager사용이 어렵거나 특정 이유로 수동 설치가 필요하다면, 크롬 공식 테스트 도구 웹사이트(https://googlechromelabs.github.io/chrome-for-testing/)에서 여러분의 크롬 브라우저 버전과 일치하는 ChromeDriver 버전을 찾아 다운로드해야 합니다. 크롬 브라우저 버전(120.x.xxxx.xx)의 주 버전(120)을 기준으로 일치하는 드라이버를 찾으세요. 다운로드 후 압축 해제한chromedriver.exe(Windows) 또는chromedriver(macOS/Linux) 파일을 파이썬 스크립트를 실행할 폴더(작업 디렉터리)에 옮겨 놓는 것이 가장 간단한 방법입니다.
2.4. 셀레니움 초기화 및 첫 실행 코드
모든 준비가 완료되었습니다! 이제 파이썬 코드를 작성하여 셀레니움이 제대로 동작하는지 확인해볼 시간입니다. 텍스트 편집기(VS Code, PyCharm 등)를 열고 first_selenium.py라는 이름으로 파일을 저장한 후, 다음 코드를 입력합니다.
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from webdriver_manager.chrome import ChromeDriverManager # 드라이버 자동 관리 라이브러리
# Chrome 옵션 설정 (선택 사항: headless 모드 등)
chrome_options = Options()
# chrome_options.add_argument("--headless") # 브라우저 창을 띄우지 않고 실행 (선택 사항)
chrome_options.add_argument("--start-maximized") # 브라우저 창을 최대화하여 시작
# WebDriverManager를 사용하여 드라이버 자동 관리 (가장 추천하는 방법)
service = Service(ChromeDriverManager().install())
driver = webdriver.Chrome(service=service, options=chrome_options)
# 웹사이트 접속
target_url = "https://www.google.com"
driver.get(target_url)
print(f"'{target_url}'에 성공적으로 접속했습니다.")
# 현재 페이지의 타이틀 출력
print(f"현재 페이지 타이틀: {driver.title}")
# 3초 대기 (페이지 로딩 확인을 위한 임시 대기)
import time
time.sleep(3)
# 브라우저 종료
driver.quit()
print("브라우저를 종료했습니다.")
코드 설명:
from webdriver_manager.chrome import ChromeDriverManager:webdriver_manager라이브러리를 사용하면, 크롬 드라이버를 수동으로 다운로드하고 경로를 지정할 필요 없이 파이썬 코드가 자동으로 드라이버를 찾아 다운로드하고 설정해줍니다.chrome_options: 브라우저의 동작 방식을 설정합니다.headless모드를 활성화하면 브라우저 창이 뜨지 않고 백그라운드에서 실행됩니다.service = Service(ChromeDriverManager().install()):ChromeDriverManager().install()을 사용하여 WebDriver 서비스 객체를 생성, 드라이버 경로를 신경 쓸 필요가 없습니다.driver = webdriver.Chrome(...): 크롬 브라우저를 제어할 WebDriver 객체를 생성합니다. 이 순간 크롬 브라우저 창이 열립니다.driver.get(target_url): 지정된 URL로 브라우저를 이동시킵니다.driver.title: 현재 웹 페이지의<title>태그 내용을 가져옵니다.time.sleep(3): 코드가 다음 동작으로 넘어가기 전에 3초 동안 기다립니다. 이는 웹 페이지가 완전히 로딩될 시간을 벌어주기 위한 임시적인 방법이며, 실제 자동화에서는 뒤에서 배울 '대기 처리' 방법을 사용합니다.driver.quit(): 열려 있던 브라우저 창을 닫고, WebDriver 세션을 종료합니다. 이는 리소스 낭비를 막고 메모리 누수를 방지하는 매우 중요한 단계입니다.
이 코드를 저장하고 터미널에서 실행해 보세요:
python first_selenium.py
# 또는
python3 first_selenium.py
크롬 브라우저가 자동으로 열리고, 구글 페이지로 이동한 다음, 잠시 후 자동으로 닫히는 것을 볼 수 있을 겁니다. 터미널에는 페이지 타이틀이 출력됩니다. 이 과정을 성공적으로 마쳤다면, 여러분은 셀레니움 개발 환경 구축을 완벽하게 해낸 것입니다! 이제 "셀레니움 파이썬 예제"를 통해 웹 자동화의 실제 동작 원리를 배워볼 준비가 되었습니다.
3. 셀레니움으로 웹 요소 찾기: find_element 완벽 활용
웹 자동화의 핵심은 웹 페이지의 특정 부분을 정확히 찾아내고 조작하는 것입니다. 웹 페이지는 단순히 눈에 보이는 그림이 아니라, 수많은 요소(Element)들이 모여 만들어진 구조물과 같습니다. 이 요소들을 찾아내기 위해 셀레니움에서는 find_element와 find_elements 메서드를 제공하며, 이를 위해 로케이터(Locator)라는 강력한 도구들을 사용합니다. 이 섹션에서는 "셀레니움 find_element 사용법"을 완벽하게 익히고, 다양한 로케이터를 활용한 실전 예제를 살펴봅니다.
3.1. 웹 요소(Web Element)와 HTML 구조 이해하기
웹 페이지는 HTML(HyperText Markup Language)로 작성됩니다. HTML 문서는 <body>, <p>, <a>, <input>, <button> 등 다양한 태그(Tag)들로 구성되며, 이 태그들은 각기 다른 역할을 하는 웹 요소를 나타냅니다. 예를 들어, <input type="text" id="username">는 'username'이라는 ID를 가진 텍스트 입력창 요소를 의미합니다.
셀레니움이 웹 요소를 찾고 조작하려면, 이 요소들이 HTML 코드 상에서 어떻게 정의되어 있는지 이해하는 것이 중요합니다. 웹 브라우저의 '개발자 도구'(대부분의 브라우저에서 F12 키로 열 수 있음)는 이 HTML 구조를 파악하는 데 매우 유용합니다.
3.2. find_element와 find_elements: 단일 vs 복수 요소 찾기
find_element(By.LOCATOR, "value"): 지정된 로케이터와 값에 해당하는 첫 번째 웹 요소를 찾아 반환합니다. 요소를 찾지 못하면NoSuchElementException에러를 발생시킵니다.find_elements(By.LOCATOR, "value"): 지정된 로케이터와 값에 해당하는 모든 웹 요소들을 찾아 리스트 형태로 반환합니다. 요소를 찾지 못해도 에러를 발생시키지 않고 빈 리스트를 반환합니다.
주로 find_element를 사용하여 특정 버튼이나 입력창과 같이 고유한 요소를 찾고, find_elements를 사용하여 테이블의 모든 행이나 게시글 목록과 같이 여러 개의 유사한 요소를 찾을 때 사용합니다.
3.3. 다양한 로케이터(Locator) 종류와 사용법
셀레니움은 웹 요소를 찾기 위한 다양한 로케이터 전략을 제공합니다. By 클래스 안에 정의되어 있으며, 상황에 따라 가장 적절한 로케이터를 선택하는 것이 중요합니다.
3.3.1. ID로 찾기 (By.ID)
HTML 요소의 id 속성은 웹 페이지 내에서 유일해야 합니다. 따라서 id는 가장 빠르고 확실하게 요소를 식별할 수 있는 방법입니다.
from selenium.webdriver.common.by import By
# 예시 HTML: <input type="text" id="username_field">
username_input = driver.find_element(By.ID, "username_field")
username_input.send_keys("my_id") # 텍스트 입력
print(f"ID로 찾은 요소의 태그 이름: {username_input.tag_name}")
3.3.2. Name으로 찾기 (By.NAME)
HTML 요소의 name 속성을 이용합니다. name은 id와 달리 유일하지 않을 수 있습니다.
# 예시 HTML: <input type="password" name="password">
password_input = driver.find_element(By.NAME, "password")
password_input.send_keys("my_password")
3.3.3. Class Name으로 찾기 (By.CLASS_NAME)
HTML 요소의 class 속성을 이용합니다. 여러 요소가 같은 클래스 이름을 가질 수 있으므로, find_element는 첫 번째 요소를 반환하고, find_elements는 해당 클래스를 가진 모든 요소를 리스트로 반환합니다.
# 예시 HTML: <button class="login-button">로그인</button>
login_button = driver.find_element(By.CLASS_NAME, "login-button")
login_button.click() # 클릭 동작
3.3.4. Tag Name으로 찾기 (By.TAG_NAME)
HTML 태그 이름(예: input, button, a, div)으로 요소를 찾습니다. 주로 find_elements와 함께 사용하여 특정 태그를 가진 모든 요소를 가져올 때 유용합니다.
# 페이지의 모든 링크(<a> 태그)를 찾기
all_links = driver.find_elements(By.TAG_NAME, "a")
print(f"페이지에 있는 총 링크 수: {len(all_links)}")
for link in all_links[:5]: # 상위 5개 링크 텍스트 출력
print(link.text)
3.3.5. Link Text로 찾기 (By.LINK_TEXT)
<a> 태그(하이퍼링크)의 정확한 텍스트 내용을 이용하여 링크를 찾습니다.
# 예시 HTML: <a href="/about">회사 소개</a>
about_link = driver.find_element(By.LINK_TEXT, "회사 소개")
about_link.click()
3.3.6. Partial Link Text로 찾기 (By.PARTIAL_LINK_TEXT)
<a> 태그의 텍스트 내용 중 일부만 일치해도 요소를 찾습니다. 텍스트가 길거나 변동될 가능성이 있을 때 유용합니다.
# 예시 HTML: <a href="/products">최신 제품 둘러보기</a>
product_link = driver.find_element(By.PARTIAL_LINK_TEXT, "제품 둘러보기")
product_link.click()
3.3.7. CSS Selector로 찾기 (By.CSS_SELECTOR)
CSS 선택자(Selector)는 HTML 요소를 스타일링할 때 사용하는 문법과 동일합니다. 매우 유연하고 강력하며, ID, Class, Tag 등 거의 모든 속성을 조합하여 요소를 찾을 수 있습니다.
- ID:
#username_field - Class:
.login-button - Tag:
input - 속성:
input[name="password"] - 조합:
div.container > input#search_input(container 클래스를 가진 div 안에 있는 search_input ID를 가진 input)
# 예시 HTML: <div class="form-group"><input type="text" id="email"></div>
email_input = driver.find_element(By.CSS_SELECTOR, "div.form-group > input#email")
email_input.send_keys("test@example.com")
# 여러 요소 찾기 예시: 모든 목록 항목 찾기
list_items = driver.find_elements(By.CSS_SELECTOR, "ul > li")
print(f"CSS Selector로 찾은 목록 항목 수: {len(list_items)}")
3.3.8. XPath로 찾기 (By.XPATH)
XPath는 XML 경로 언어로, HTML 문서 내의 어떤 요소라도 경로를 통해 찾아낼 수 있는 가장 강력하고 유연한 로케이터입니다. 복잡한 구조나 특정 조건(예: n번째 자식 요소)을 만족하는 요소를 찾을 때 유용합니다. 하지만 코드가 길어지고 가독성이 떨어질 수 있으며, 웹 페이지 구조 변경에 취약하다는 단점도 있습니다.
- 절대 경로:
/html/body/div[1]/form/input[1](페이지 구조가 조금만 바뀌어도 깨질 위험) - 상대 경로:
//input[@id="username_field"](ID가 username_field인 모든 input 태그) - 속성 기반:
//button[contains(text(), '로그인')](텍스트에 '로그인'이 포함된 버튼)
# 예시 HTML: <input type="submit" value="로그인">
# XPath: //input[@type='submit' and @value='로그인']
submit_button = driver.find_element(By.XPATH, "//input[@type='submit' and @value='로그인']")
submit_button.click()
# 특정 텍스트를 가진 요소 찾기
# 예시 HTML: <span>환영합니다, 사용자님!</span>
welcome_message = driver.find_element(By.XPATH, "//span[contains(text(), '환영합니다')]")
print(f"환영 메시지: {welcome_message.text}")
3.4. 웹 요소의 기본 동작: send_keys, click, text
요소를 찾았다면 이제 이 요소들을 조작해야겠죠? 셀레니움에서 가장 많이 사용되는 세 가지 기본 동작입니다.
send_keys("텍스트"): 입력 필드(input,textarea)에 텍스트를 입력합니다.click(): 버튼, 링크 등 클릭 가능한 요소를 클릭합니다..text: 요소 내부에 있는 텍스트 콘텐츠를 가져옵니다.
실전 find_element 종합 예제:
가상의 검색 엔진 페이지에서 검색어를 입력하고, 검색 버튼을 클릭한 후, 결과 페이지의 특정 텍스트를 가져오는 시나리오를 생각해봅시다.
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from webdriver_manager.chrome import ChromeDriverManager
import time
# Chrome 옵션 설정
chrome_options = Options()
chrome_options.add_argument("--start-maximized")
# WebDriverManager를 사용하여 드라이버 자동 관리
service = Service(ChromeDriverManager().install())
driver = webdriver.Chrome(service=service, options=chrome_options)
try:
# 1. 검색 엔진 접속 (실제 구글 사용)
driver.get("https://www.google.com")
print("구글에 접속했습니다.")
time.sleep(1) # 페이지 로딩 대기
# 2. 검색 입력창 찾기 (name 속성 사용)
search_box = driver.find_element(By.NAME, "q")
print("검색창을 찾았습니다.")
# 3. 검색어 입력
search_query = "셀레니움 웹 자동화"
search_box.send_keys(search_query)
print(f"검색어 '{search_query}'를 입력했습니다.")
time.sleep(1)
# 4. 검색 버튼 클릭 (Enter 키 입력으로 대체)
search_box.submit() # send_keys 이후 submit()을 호출하여 Enter 키 누름 효과
print("검색 버튼을 클릭했습니다 (Enter 키 입력).")
time.sleep(3) # 검색 결과 페이지 로딩 대기
# 5. 검색 결과에서 특정 정보 추출 (CSS Selector 사용)
# 이 CSS Selector는 구글 검색 결과의 첫 번째 제목 요소를 찾는 데 사용될 수 있습니다.
first_result_title = driver.find_element(By.CSS_SELECTOR, "h3.LC20lb.MBeuO.DKV0Md")
print(f"첫 번째 검색 결과 제목: {first_result_title.text}")
except Exception as e:
print(f"오류 발생: {e}")
finally:
# 6. 브라우저 종료
driver.quit()
print("브라우저를 종료했습니다.")
이 예제를 통해 여러분은 다양한 로케이터를 사용하여 웹 요소를 찾고, send_keys와 click (또는 submit())을 이용해 조작하며, .text 속성으로 정보를 추출하는 "셀레니움 파이썬 예제"의 기본 패턴을 익혔습니다. 웹 페이지의 구조를 파악하고 적절한 로케이터를 선택하는 연습을 꾸준히 한다면, 어떤 웹사이트라도 여러분의 코드 아래 놓이게 될 것입니다.
4. 셀레니움 동적 페이지 처리: 안정적인 대기 전략
현대의 웹 페이지는 과거와 달리 정적이지 않습니다. JavaScript를 통해 콘텐츠가 동적으로 로딩되거나, 사용자 상호작용에 따라 페이지 내용이 비동기적으로 업데이트되는 경우가 흔합니다. 이러한 동적인 환경에서 셀레니움 자동화를 안정적으로 수행하려면, 웹 페이지가 완전히 로딩되거나 특정 요소가 나타날 때까지 '기다리는' 전략이 필수적입니다. 이 섹션에서는 "셀레니움 대기 처리 방법"의 핵심인 암시적 대기(Implicit Waits)와 명시적 대기(Explicit Waits)를 집중적으로 다루고, 안정적인 자동화 코드를 작성하는 방법을 제시합니다.
4.1. 왜 기다려야 하는가? 동적 웹 페이지의 문제점
셀레니움 코드는 매우 빠르게 실행됩니다. 하지만 웹 브라우저가 웹 페이지를 로딩하고, JavaScript를 실행하며, 서버로부터 데이터를 받아와 화면에 요소를 그리는 데는 시간이 걸립니다. 만약 셀레니움 코드가 아직 로딩되지 않은 요소를 찾으려 시도한다면, NoSuchElementException과 같은 에러가 발생하며 자동화 스크립트가 중단될 것입니다.
초보자들이 흔히 사용하는 time.sleep()은 코드의 실행을 지정된 시간만큼 무조건 멈추는 가장 단순한 대기 방법입니다. 하지만 이는 비효율적입니다. 페이지 로딩 시간은 가변적이므로, 셀레니움은 이러한 문제를 해결하기 위한 더 스마트한 대기 방법을 제공합니다.
4.2. 암시적 대기 (Implicit Waits)
암시적 대기(Implicit Waits)는 WebDriver가 요소를 찾을 때, 지정된 최대 시간 동안 웹 페이지의 모든 요소가 존재할 때까지 기다리도록 지시하는 전역 설정입니다. 한 번 설정하면 WebDriver 인스턴스가 살아있는 동안 모든 find_element (또는 find_elements) 호출에 적용됩니다.
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from webdriver_manager.chrome import ChromeDriverManager
import time
service = Service(ChromeDriverManager().install())
driver = webdriver.Chrome(service=service)
# 암시적 대기 설정: 최대 10초까지 기다립니다.
driver.implicitly_wait(10) # 10초
try:
driver.get("https://example.com/dynamic_page") # 가상의 동적 페이지
# 여기서부터 모든 find_element 호출은 최대 10초까지 기다립니다.
# 만약 요소가 2초만에 나타나면 2초 후에 바로 다음 코드가 실행됩니다.
# 10초가 지나도 요소가 나타나지 않으면 NoSuchElementException 발생.
dynamic_element = driver.find_element(By.ID, "some_dynamic_id")
print(f"동적 요소 텍스트: {dynamic_element.text}")
except Exception as e:
print(f"오류 발생: {e}")
finally:
driver.quit()
장점:
- 간단하게 한 번만 설정하면 되므로 코드가 간결해집니다.
- 요소가 발견되면 즉시 다음 단계로 넘어가므로
time.sleep()보다 효율적입니다.
단점:
- 모든
find_element호출에 적용되어 유연성이 떨어질 수 있습니다. - 존재하지 않는 요소를 찾는 경우, 항상 최대 대기 시간만큼 기다린 후에야
NoSuchElementException을 발생시켜 디버깅 시 시간을 지연시킬 수 있습니다.
4.3. 명시적 대기 (Explicit Waits)
명시적 대기(Explicit Waits)는 특정 조건이 충족될 때까지, 또는 최대 지정된 시간까지 기다리도록 코드를 통해 명확하게 지시하는 방법입니다. 암시적 대기와 달리, 특정 요소나 특정 조건에 대해서만 적용되며 훨씬 더 유연하고 강력합니다. WebDriverWait 클래스와 expected_conditions 모듈을 조합하여 사용합니다.
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait # WebDriverWait 임포트
from selenium.webdriver.support import expected_conditions as EC # expected_conditions 임포트
from webdriver_manager.chrome import ChromeDriverManager
import time
service = Service(ChromeDriverManager().install())
driver = webdriver.Chrome(service=service)
try:
driver.get("https://www.naver.com") # 네이버 접속
print("네이버에 접속했습니다.")
# 네이버 검색창 (ID: query)이 클릭 가능할 때까지 최대 10초 기다림
search_input = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.ID, "query"))
)
print("네이버 검색창이 클릭 가능해질 때까지 기다렸습니다.")
search_input.send_keys("셀레니움")
print("검색어 '셀레니움' 입력.")
time.sleep(1)
# 네이버 검색 버튼 (ID: search_btn)이 클릭 가능할 때까지 대기
search_button = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.ID, "search_btn"))
)
print("검색 버튼이 클릭 가능해질 때까지 기다렸습니다.")
search_button.click()
print("검색 버튼 클릭.")
# 검색 결과 페이지에서 특정 요소(예: 뉴스 탭)가 나타날 때까지 대기
news_tab = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.LINK_TEXT, "뉴스"))
)
print(f"뉴스 탭이 나타났습니다. 텍스트: {news_tab.text}")
time.sleep(3)
except Exception as e:
print(f"오류 발생: {e}")
finally:
driver.quit()
print("브라우저를 종료했습니다.")
expected_conditions의 주요 조건들:
presence_of_element_located((By.LOCATOR, "value")): 요소가 DOM에 존재할 때까지.visibility_of_element_located((By.LOCATOR, "value")): 요소가 DOM에 존재하고 화면에 보일 때까지.element_to_be_clickable((By.LOCATOR, "value")): 요소가 화면에 보이고 클릭 가능할 때까지.text_to_be_present_in_element((By.LOCATOR, "value"), "text"): 특정 요소에 특정 텍스트가 나타날 때까지.
장점:
- 특정 조건이 충족될 때까지 기다리므로 가장 효율적이고 안정적입니다.
- 세밀한 제어가 가능하여 복잡한 동적 페이지 자동화에 적합합니다.
TimeoutException을 통해 대기 시간 초과 시 명확하게 처리할 수 있습니다.
4.4. Implicit Waits와 Explicit Waits, 그리고 주의할 점
두 가지 대기 방법을 혼용할 수는 있지만, 암시적 대기와 명시적 대기를 동시에 사용하는 것은 권장되지 않습니다. 예상치 못한 대기 시간 증가나 동작 오류가 발생할 수 있기 때문입니다.
따라서, 일반적으로는 명시적 대기(Explicit Waits)만을 사용하는 것이 가장 안정적이고 효율적인 "셀레니움 대기 처리 방법"으로 권장됩니다. 꼭 필요한 경우에만 time.sleep()을 짧게 사용하는 것을 고려할 수 있습니다.
안정적인 웹 자동화를 위해서는 페이지의 동적 특성을 이해하고, WebDriverWait와 expected_conditions를 적극적으로 활용하여 요소가 준비될 때까지 기다리는 '기다림의 미학'을 실천하는 것이 핵심입니다. 이를 통해 "셀레니움 웹 자동화" 스크립트의 견고성과 신뢰성을 크게 향상시킬 수 있습니다.
5. 셀레니움 실전 프로젝트: 로그인 & 웹 스크래핑 자동화
지금까지 배운 셀레니움의 모든 지식을 한데 모아 실제 웹사이트에 적용해 볼 시간입니다. 이 섹션에서는 가상의 웹사이트에서 "셀레니움 로그인 자동화"를 구현하고, 로그인 후 "셀레니움 웹 크롤링 예제"를 통해 특정 정보를 스크래핑하는 과정을 단계별로 보여드리겠습니다. 이는 "셀레니움 웹 자동화"의 진정한 가치를 느끼게 해 줄 실전 프로젝트가 될 것입니다.
주의: 실제 웹사이트를 대상으로 자동화/스크래핑을 할 때는 해당 웹사이트의 이용 약관 및 로봇 배제 표준(robots.txt)을 반드시 확인하고 준수해야 합니다. 과도한 요청이나 불법적인 데이터 수집은 서비스 약관 위반 및 법적 문제로 이어질 수 있습니다. 여기서는 교육 목적으로 가상의 웹사이트 또는 접근이 허용된 공개 페이지를 대상으로 가정하여 설명합니다.
5.1. 프로젝트 시나리오: 가상 로그인 및 게시글 제목 추출
우리의 목표는 다음과 같습니다.
- 가상의 로그인 페이지(
https://example.com/login)에 접속합니다. - 사용자 ID와 비밀번호를 입력하고 로그인 버튼을 클릭하여 로그인합니다.
- 로그인 성공 후 나타나는 마이 페이지(
https://example.com/mypage) 또는 게시판 페이지로 이동합니다. - 게시판에서 최근 게시글 5개의 제목을 추출합니다.
- 브라우저를 종료합니다.
5.2. 실전 코드 구현
아래 코드는 가상의 example.com을 대상으로 작성되었으므로, 실제 웹사이트에 적용하려면 해당 사이트의 HTML 구조에 맞춰 로케이터를 수정해야 합니다.
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from webdriver_manager.chrome import ChromeDriverManager
import time
# 1. WebDriver 설정 및 브라우저 실행
chrome_options = Options()
chrome_options.add_argument("--start-maximized") # 브라우저 창 최대화
# chrome_options.add_argument("--headless") # 선택 사항: 브라우저 창 없이 백그라운드 실행
service = Service(ChromeDriverManager().install())
driver = webdriver.Chrome(service=service, options=chrome_options)
driver.implicitly_wait(5) # 암시적 대기 설정 (요소가 나타날 때까지 최대 5초 대기)
try:
# 2. 로그인 페이지 접속
login_url = "https://example.com/login" # 가상의 로그인 페이지 URL
driver.get(login_url)
print(f"로그인 페이지 '{login_url}'에 접속했습니다.")
# 3. 로그인 정보 입력 및 로그인 버튼 클릭
user_id = "testuser"
user_pw = "testpass"
# 사용자 이름 입력 필드 찾기 및 입력
username_field = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, "username"))
)
username_field.send_keys(user_id)
print(f"사용자 ID '{user_id}' 입력 완료.")
# 비밀번호 입력 필드 찾기 및 입력
password_field = driver.find_element(By.ID, "password")
password_field.send_keys(user_pw)
print(f"비밀번호 입력 완료.")
# 로그인 버튼 찾기 및 클릭
login_button = driver.find_element(By.ID, "login_btn")
login_button.click()
print("로그인 버튼 클릭 완료.")
# 4. 로그인 성공 후 페이지 이동 확인 (명시적 대기)
WebDriverWait(driver, 10).until(
EC.url_to_be("https://example.com/mypage") # 특정 URL로 이동할 때까지 대기
)
print(f"로그인 성공! 현재 URL: {driver.current_url}")
time.sleep(2) # 페이지 내용 로딩 추가 대기
# 5. 게시글 목록에서 정보 스크래핑
print("\n게시글 목록 스크래핑 시작...")
# 모든 게시글 제목 요소 찾기
post_titles = driver.find_elements(By.CLASS_NAME, "post-title")
if post_titles:
print(f"총 {len(post_titles)}개의 게시글 제목을 찾았습니다. 상위 5개 출력:")
for i, title_element in enumerate(post_titles[:5]): # 상위 5개만 추출
print(f"- {i+1}. {title_element.text}")
else:
print("게시글 제목 요소를 찾을 수 없습니다. HTML 구조를 확인하세요.")
time.sleep(3) # 결과 확인용
except Exception as e:
print(f"자동화 중 오류 발생: {e}")
# 오류 발생 시 현재 화면 캡처 (디버깅에 유용)
driver.save_screenshot("error_screenshot.png")
print("오류 스크린샷 'error_screenshot.png'를 저장했습니다.")
finally:
# 6. 브라우저 종료
driver.quit()
print("\n브라우저를 종료했습니다.")
코드 분석 및 확장:
- 로케이터 선택의 중요성: 위 코드에서는
By.ID와By.CLASS_NAME을 주로 사용했습니다. 실제 웹사이트에서는 개발자 도구(F12)를 사용하여 각 요소의 속성을 확인하고, 필요에 따라By.CSS_SELECTOR나By.XPATH를 조합하여 가장 견고한 로케이터를 선택해야 합니다. - 대기 전략: 로그인 성공 후
EC.url_to_be를 사용하여 페이지 전환을 기다리는 명시적 대기를 사용했습니다. 이는time.sleep()보다 훨씬 안정적이며 효율적입니다. - 오류 처리:
try...except...finally블록을 사용하여 자동화 과정에서 발생할 수 있는 오류를 포착하고,driver.save_screenshot()을 통해 오류 발생 시 화면을 캡처하여 디버깅을 용이하게 했습니다. 이는 "셀레니움 에러 해결"에 매우 중요한 부분입니다. - 스크래핑 결과 활용: 추출한
post_titles리스트의 각title_element.text는 게시글의 제목 문자열입니다. 이 데이터를 파일로 저장하거나, 데이터베이스에 넣거나, 추가 분석을 위해 다른 파이썬 라이브러리(예:pandas)로 넘기는 등 다양한 방식으로 활용할 수 있습니다.
이 실전 프로젝트는 셀레니움을 이용한 "셀레니움 웹 자동화" 및 "셀레니움 웹 크롤링 예제"의 기본적인 흐름을 보여줍니다. 여러분은 이 코드를 바탕으로 실제 관심 있는 웹사이트의 로그인 과정을 자동화하거나, 필요한 정보를 스크래핑하는 코드를 직접 작성해볼 수 있습니다. 중요한 것은 웹 페이지의 구조를 정확히 이해하고, 적절한 로케이터와 대기 전략을 사용하는 꾸준한 연습입니다.
6. 셀레니움 고급 활용 팁 & 문제 해결 가이드
셀레니움을 사용하여 웹 자동화를 구현하다 보면, 단순히 코드를 작성하는 것을 넘어 효율성과 안정성을 높이기 위한 다양한 팁과, 마주칠 수 있는 흔한 문제들에 대한 해결책을 알아두는 것이 중요합니다. 이 섹션에서는 "셀레니움 에러 해결"에 필수적인 정보들을 제공하고, 고급 활용 팁을 소개합니다.
6.1. 셀레니움 활용 팁: 효율성 높이기
6.1.1. Headless 모드 활용: 보이지 않는 브라우저
셀레니움은 브라우저를 화면에 띄우지 않고 백그라운드에서 실행하는 Headless 모드를 지원합니다. 이는 다음과 같은 경우에 매우 유용합니다.
- 서버 환경: GUI(그래픽 사용자 인터페이스)가 없는 서버에서 자동화를 실행할 때.
- 성능 향상: 브라우저 렌더링에 필요한 자원을 줄여 속도를 높이고 메모리 사용량을 감소시킬 때.
- 백그라운드 작업: 사용자가 화면을 보지 않아도 되는 자동화 작업을 수행할 때.
Headless 모드 설정 방법:
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
chrome_options = Options()
chrome_options.add_argument("--headless") # 이 한 줄로 Headless 모드 활성화
chrome_options.add_argument("--window-size=1920,1080") # Headless에서도 화면 크기 지정 권장
chrome_options.add_argument("--disable-gpu") # 일부 리눅스 시스템에서 필요할 수 있음
service = Service(ChromeDriverManager().install())
driver = webdriver.Chrome(service=service, options=chrome_options)
try:
driver.get("https://www.naver.com")
print(f"Headless 모드로 네이버에 접속했습니다. 타이틀: {driver.title}")
driver.save_screenshot("headless_naver.png") # 스크린샷으로 확인 가능
print("스크린샷 'headless_naver.png'를 저장했습니다.")
except Exception as e:
print(f"오류 발생: {e}")
finally:
driver.quit()
6.1.2. User-Agent 설정: 봇 감지 우회 및 특정 환경 시뮬레이션
일부 웹사이트는 봇(Bot)의 접근을 막기 위해 User-Agent 값을 확인합니다. User-Agent는 웹 브라우저나 클라이언트 프로그램이 서버에 자신을 식별하는 데 사용하는 문자열입니다. 필요에 따라 특정 User-Agent를 설정하여 웹사이트의 봇 감지를 우회하거나, 모바일 환경 등을 시뮬레이션할 수 있습니다.
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
chrome_options = Options()
# 원하는 User-Agent 문자열로 설정 (예: 일반적인 Chrome User-Agent 또는 모바일 User-Agent)
user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.88 Safari/537.36"
chrome_options.add_argument(f"user-agent={user_agent}")
service = Service(ChromeDriverManager().install())
driver = webdriver.Chrome(service=service, options=chrome_options)
try:
driver.get("https://whatismybrowser.com/detect/what-is-my-user-agent") # User-Agent 확인 사이트
print(f"User-Agent를 '{user_agent}'로 설정하여 접속했습니다.")
import time
time.sleep(5)
except Exception as e:
print(f"오류 발생: {e}")
finally:
driver.quit()
6.1.3. 프록시 설정: IP 우회 및 익명성 유지
대량의 웹 스크래핑 시, 동일 IP 주소에서 반복 요청이 발생하면 웹사이트에 의해 차단될 수 있습니다. 이럴 때 프록시 서버를 경유하여 요청을 보내면 IP 주소를 우회하여 차단을 피할 수 있습니다.
# 프록시 설정 예시 (실제 동작하는 프록시 서버 주소 필요)
proxy_server = "IP주소:포트번호" # 예: "192.168.1.1:8080"
chrome_options.add_argument(f"--proxy-server={proxy_server}")
Note: 인증이 필요한 프록시의 경우 추가적인 설정이 필요합니다.
6.2. 셀레니움 자주 겪는 문제 해결 가이드: "셀레니움 에러 해결"
셀레니움 자동화를 하다 보면 다양한 에러에 부딪히게 됩니다. 당황하지 마세요! 대부분의 에러는 흔히 발생하며, 해결책 또한 명확합니다.
6.2.1. NoSuchElementException: 요소를 찾을 수 없을 때
가장 흔하게 발생하는 에러입니다. find_element 메서드가 지정된 로케이터로 요소를 찾지 못했을 때 발생합니다.
원인 및 해결책:
- 잘못된 로케이터: 개발자 도구(
F12)로 요소의 정확한 ID, Class, XPath, CSS Selector를 확인하고 수정합니다. - 요소 로딩 지연: 명시적 대기(
WebDriverWait와expected_conditions)를 사용하여 요소가 나타날 때까지 기다립니다. - 프레임(iframe): 요소가 다른
<iframe>내부에 있다면,driver.switch_to.frame("frame_id_or_name")등으로 해당 프레임으로 컨텍스트를 전환해야 합니다. 프레임 밖으로 나올 때는driver.switch_to.default_content()를 사용합니다.
6.2.2. StaleElementReferenceException: '오래된' 요소 참조
이미 찾은 웹 요소에 대해 조작을 시도했는데, 해당 요소가 웹 페이지의 DOM(문서 객체 모델)에서 더 이상 존재하지 않거나 변경되었을 때 발생합니다. 웹 페이지가 새로 로딩되거나, JavaScript에 의해 DOM이 업데이트될 때 흔히 발생합니다.
원인 및 해결책:
- 요소를 다시 찾기:
StaleElementReferenceException이 발생하면, 해당 요소를 다시driver.find_element()를 통해 찾아 참조를 업데이트해야 합니다. - 명시적 대기 활용:
WebDriverWait를 사용하여 요소가 다시 나타나거나 클릭 가능해질 때까지 기다리는 로직을 추가합니다.
# StaleElementReferenceException 해결 예시
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
# ... (driver 설정) ...
try:
driver.get("https://example.com/dynamic_list")
first_item = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.CSS_SELECTOR, "#list_container li:first-child"))
)
print(f"첫 번째 아이템 텍스트: {first_item.text}")
# (가정) 리스트를 새로고침하는 버튼 클릭으로 인해 DOM 업데이트
driver.find_element(By.ID, "refresh_button").click()
# 새로운 참조를 얻기 위해 요소를 다시 찾음
# EC.staleness_of(first_item)을 사용하여 이전 요소가 stale해질 때까지 기다릴 수도 있습니다.
new_first_item = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.CSS_SELECTOR, "#list_container li:first-child"))
)
print(f"업데이트된 첫 번째 아이템 텍스트: {new_first_item.text}")
except Exception as e:
print(f"오류 발생: {e}")
finally:
driver.quit()
6.2.3. TimeoutException: 대기 시간 초과
명시적 대기(WebDriverWait)를 사용했을 때, 지정된 시간 내에 expected_conditions가 충족되지 않으면 발생합니다.
원인 및 해결책:
- 대기 시간 늘리기:
WebDriverWait(driver, 20)처럼 대기 시간을 충분히 늘려봅니다. - 조건 다시 확인:
expected_conditions의 조건이 웹 페이지의 실제 동작과 일치하는지 확인합니다. - 네트워크 상태 확인: 웹 페이지 로딩 속도가 너무 느리다면 네트워크 상태를 점검하거나,
try-except블록으로 예외 처리를 해줍니다.
6.2.4. WebDriverException 또는 SessionNotCreatedException: 드라이버 문제
이 에러는 WebDriver가 브라우저를 시작할 때 발생합니다.
원인 및 해결책:
- 크롬 드라이버 버전 불일치:
webdriver_manager라이브러리를 사용하거나, 수동으로 크롬 브라우저 버전에 맞는chromedriver를 다운로드하여 업데이트합니다. - 드라이버 경로 오류:
chromedriver파일이PATH환경 변수에 등록되었는지, 또는 스크립트와 같은 폴더에 있는지 확인합니다. - 브라우저 설치 오류: 크롬 브라우저 자체를 재설치해 보는 것도 방법입니다.
이러한 팁과 문제 해결 방법을 익히는 것은 여러분의 "셀레니움 웹 자동화" 여정을 훨씬 더 부드럽고 효율적으로 만들어 줄 것입니다. 항상 개발자 도구를 친구 삼아 웹 페이지의 구조를 파악하고, 에러 메시지를 주의 깊게 읽는 습관을 들이는 것이 중요합니다.
7. 셀레니움 다음 단계: 효율적인 웹 자동화 전략과 대안
셀레니움은 웹 자동화와 스크래핑을 위한 강력하고 유용한 도구이지만, 모든 상황에 완벽한 만능 해결책은 아닙니다. 어떤 도구든 장점과 한계점을 명확히 이해하고, 필요에 따라 다른 도구와 조합하거나 대체제를 활용하는 것이 현명한 접근 방식입니다. 이 섹션에서는 셀레니움의 한계점을 짚어보고, 다른 웹 자동화/스크래핑 도구들을 간략히 소개하며, 효율적인 자동화 코드 작성을 위한 베스트 프랙티스를 제시합니다.
7.1. 셀레니움의 한계점
- 성능 및 자원 소모: 셀레니움은 실제 브라우저를 실행하므로, 메모리나 CPU와 같은 시스템 자원을 많이 소모합니다. 대규모 웹 크롤링이나 수많은 동시 작업 시 병목 현상을 일으킬 수 있습니다.
- 속도: 실제 브라우저를 띄우고 페이지를 렌더링하는 과정 자체가 시간이 오래 걸릴 수 있습니다. 매우 빠른 속도로 데이터만 추출해야 하는 경우에는 비효율적일 수 있습니다.
- 복잡한 코드 구조: 동적 페이지 처리, 대기 처리, 오류 처리 등을 모두 고려하면 스크립트의 길이가 길어지고 복잡해질 수 있습니다.
- 봇 감지: 일부 웹사이트는 셀레니움과 같은 자동화 도구의 접근을 탐지하고 차단하는 고급 봇 감지 시스템을 사용합니다. 이를 우회하기 위한 추가적인 노력이 필요할 수 있습니다.
7.2. 더 나은 웹 자동화를 위한 대안 도구들
셀레니움 외에도 다양한 웹 자동화 및 스크래핑 도구들이 있으며, 각각의 장단점이 뚜렷합니다. 여러분의 프로젝트 목표와 웹사이트의 특성에 따라 적절한 도구를 선택하는 것이 중요합니다.
7.2.1. Requests & BeautifulSoup: 정적 웹 페이지 스크래핑의 강자
- Requests: HTTP 요청을 보내고 응답을 받는 데 특화된 파이썬 라이브러리입니다. 브라우저 없이 직접 웹 서버와 통신하므로 매우 빠르고 가볍습니다.
- BeautifulSoup: Requests로 가져온 HTML/XML 텍스트를 파싱(분석)하여 원하는 데이터를 쉽게 추출할 수 있도록 돕는 라이브러리입니다.
주요 활용: JavaScript 실행 없이 모든 콘텐츠가 HTML에 담겨 있는 정적 웹 페이지에서 데이터를 효율적으로 스크래핑할 때 최적입니다. 셀레니움보다 훨씬 빠르고 자원 소모가 적습니다.
import requests
from bs4 import BeautifulSoup
url = "https://www.naver.com" # 예시: 네이버의 정적 요소 스크래핑
response = requests.get(url)
if response.status_code == 200:
soup = BeautifulSoup(response.text, 'html.parser')
# 네이버의 뉴스 섹션 제목 스크래핑 (예시)
news_titles = soup.select('.news_area .news_tit') # CSS Selector 사용
for i, title in enumerate(news_titles[:5]):
print(f"{i+1}. {title.get_text(strip=True)}")
else:
print(f"페이지 접속 실패: {response.status_code}")
7.2.2. Playwright & Puppeteer: 현대적인 브라우저 자동화 프레임워크
- Playwright (파이썬, Node.js, Java 등 지원): Microsoft에서 개발한 브라우저 자동화 라이브러리로, Chrome, Firefox, WebKit(Safari) 등 여러 브라우저를 하나의 API로 제어할 수 있습니다. 셀레니움과 유사하게 실제 브라우저를 제어하지만, 비동기(async/await) 지원이 강력하고, 자동 대기 기능이 내장되어 있어 셀레니움보다 더 안정적이고 빠르게 동작하는 경우가 많습니다.
- Puppeteer (Node.js 전용): Google에서 개발한 Chrome/Chromium 브라우저 자동화 라이브러리입니다. 주로 Node.js 환경에서 사용되며, Headless Chrome을 효과적으로 제어할 수 있습니다.
주요 활용: 셀레니움과 같이 JavaScript 기반의 동적 웹 페이지를 자동화하고 스크래핑할 때 사용됩니다. 특히 최신 웹 기술을 적극적으로 활용하며, 셀레니움보다 더 나은 성능과 개발자 경험을 제공할 수 있습니다.
# Playwright 예시 (파이썬) - pip install playwright 설치 후 playwright install 실행
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
page = browser.new_page()
page.goto("https://www.google.com")
page.fill('textarea[name="q"]', "Playwright 웹 자동화")
page.press('textarea[name="q"]', "Enter")
page.wait_for_selector('h3') # 결과 페이지의 h3 태그가 나타날 때까지 자동 대기
print(page.title())
browser.close()
7.3. 더 나은 자동화를 위한 베스트 프랙티스
어떤 도구를 사용하든, 효과적인 웹 자동화를 위한 몇 가지 공통적인 베스트 프랙티스가 있습니다.
- 모듈화된 코드 작성: 코드를 기능별로 분리하여 함수나 클래스로 만드세요. 재사용성과 유지보수성이 크게 향상됩니다.
- 명시적 대기 적극 활용:
time.sleep()대신WebDriverWait와expected_conditions를 사용하여 요소가 나타날 때까지 기다리는 것이 가장 안정적인 방법입니다. - 로케이터의 견고성: ID, CSS Selector를 우선적으로 고려하고, XPath는 최후의 수단으로 사용하는 것이 좋습니다. 웹 페이지 구조 변경에 가장 영향을 덜 받는 로케이터를 선택하세요.
- 오류 처리 및 로깅:
try-except블록을 사용하여 예상치 못한 오류에 대비하고, 로그를 남겨 자동화 과정의 문제를 추적하세요.driver.save_screenshot()은 오류 발생 시 상황 파악에 매우 유용합니다. - 브라우저 종료 (
driver.quit()): 자동화 작업이 끝난 후에는 반드시driver.quit()를 호출하여 WebDriver 세션을 종료하고, 브라우저 프로세스를 완전히 종료해야 합니다. robots.txt및 이용 약관 확인: 웹 스크래핑 시에는 항상 대상 웹사이트의robots.txt파일(예:https://example.com/robots.txt)과 이용 약관을 확인하여 합법적인 범위 내에서 데이터를 수집해야 합니다.
셀레니움은 웹 자동화의 세계로 들어서는 훌륭한 첫걸음입니다. 이 가이드를 통해 여러분은 셀레니움의 기본부터 실전 활용, 그리고 문제 해결에 이르기까지 폭넓은 지식을 습득했을 것입니다. 이제 배운 내용을 바탕으로 꾸준히 연습하고, 필요에 따라 더 심화된 기술과 다른 도구들을 탐구하며 웹 자동화 전문가로 거듭나시길 바랍니다!
참고 자료:
- Selenium 공식 문서: https://www.selenium.dev/documentation/ko/
- ChromeDriver 공식 다운로드 (Chrome for Testing): https://googlechromelabs.github.io/chrome-for-testing/
- Python 공식 웹사이트: https://www.python.org/
- Requests 라이브러리: https://requests.readthedocs.io/en/latest/
- BeautifulSoup 라이브러리: https://www.crummy.com/software/BeautifulSoup/bs4/doc/
- Playwright 공식 문서: https://playwright.dev/python/docs/intro
'DEV > ETC' 카테고리의 다른 글
| 안티그래비티 IDE: 미래 개발 환경 최적화와 생산성 향상 전략 (0) | 2026.01.03 |
|---|---|
| 파이썬 주식 자동매매: 비전공자를 위한 실전 가이드 (첫걸음부터 고급 전략까지) (0) | 2026.01.03 |
| TDD(테스트 주도 개발): 견고한 코드와 리팩토링 자신감으로 개발 생산성 극대화하기 (0) | 2026.01.03 |
| 분산 메시징 시스템 핵심 비교: SQS, SNS, Kafka, RabbitMQ 최적 선택 가이드 (0) | 2026.01.03 |
| 프롬프트 고급 기술: GPT 활용을 극대화하는 비결 (0) | 2026.01.03 |
- Total
- Today
- Yesterday
- 웹스크래핑
- n8n
- 오픈소스DB
- llm최적화
- 크로미움
- 배민문방구
- 펄
- 도커
- springboot
- selenium
- 코드생성AI
- Java
- 업무자동화
- spring프레임워크
- 해외
- 배민
- 프롬프트엔지니어링
- SEO최적화
- Oracle
- 직구
- AI솔루션
- Rag
- 비즈니스성장
- 개발생산성
- 생산성향상
- 데이터베이스
- restapi
- springai
- 웹개발
- 자바AI개발
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | ||||
| 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| 11 | 12 | 13 | 14 | 15 | 16 | 17 |
| 18 | 19 | 20 | 21 | 22 | 23 | 24 |
| 25 | 26 | 27 | 28 | 29 | 30 | 31 |