
웹 개발과 테스팅 분야에서 빠질 수 없는 도구, 셀레니움(Selenium)에 대해 알아보겠습니다. 반복적인 웹 작업을 자동화하고 싶거나, 웹 애플리케이션을 테스트하고 싶다면 이 글이 도움이 될 것입니다!

Copy# 셀레니움 설치
pip install selenium
# 브라우저 드라이버 자동 관리 도구 설치
pip install webdriver-manager
셀레니움은 각 브라우저별로 드라이버가 필요합니다:
webdriver-manager를 사용하면 드라이버를 자동으로 다운로드하고 관리할 수 있습니다!
Copyfrom selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
# Chrome 브라우저 자동 설정
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
# 웹 페이지 열기
driver.get("https://www.google.com")
# 페이지 제목 출력
print(driver.title)
# 브라우저 종료
driver.quit()
Copyfrom selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
import time
# 브라우저 설정
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
try:
# Google 검색 페이지로 이동
driver.get("https://www.google.com")
# 검색창 찾기
search_box = driver.find_element(By.NAME, "q")
# 검색어 입력
search_box.send_keys("셀레니움 사용법")
# Enter 키 누르기
search_box.send_keys(Keys.RETURN)
# 3초 대기
time.sleep(3)
# 첫 번째 검색 결과 클릭
first_result = driver.find_element(By.CSS_SELECTOR, "h3")
first_result.click()
# 5초 대기
time.sleep(5)
finally:
# 브라우저 종료
driver.quit()
Copyfrom selenium.webdriver.common.by import By
# ID로 찾기
element = driver.find_element(By.ID, "myId")
# 클래스명으로 찾기
element = driver.find_element(By.CLASS_NAME, "myClass")
# 태그명으로 찾기
element = driver.find_element(By.TAG_NAME, "div")
# CSS 선택자로 찾기
element = driver.find_element(By.CSS_SELECTOR, ".myClass > div")
# XPath로 찾기
element = driver.find_element(By.XPATH, "//div[@class='myClass']")
# 링크 텍스트로 찾기
element = driver.find_element(By.LINK_TEXT, "클릭하세요")
# 부분 링크 텍스트로 찾기
element = driver.find_element(By.PARTIAL_LINK_TEXT, "클릭")
Copyfrom selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
def auto_login(username, password, login_url):
# 브라우저 설정
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
try:
# 로그인 페이지로 이동
driver.get(login_url)
# 요소가 로드될 때까지 대기 (최대 10초)
wait = WebDriverWait(driver, 10)
# 사용자명 입력 필드 찾기 및 입력
username_field = wait.until(
EC.presence_of_element_located((By.NAME, "username"))
)
username_field.send_keys(username)
# 비밀번호 입력 필드 찾기 및 입력
password_field = driver.find_element(By.NAME, "password")
password_field.send_keys(password)
# 로그인 버튼 클릭
login_button = driver.find_element(By.XPATH, "//button[@type='submit']")
login_button.click()
# 로그인 성공 확인 (예: 대시보드 페이지 제목 확인)
wait.until(EC.title_contains("Dashboard"))
print("로그인 성공!")
return driver
except Exception as e:
print(f"로그인 실패: {e}")
driver.quit()
return None
# 사용 예시
# driver = auto_login("my_username", "my_password", "https://example.com/login")

웹 페이지가 로딩되는 시간을 고려해야 합니다:
Copy# 요소를 찾을 때까지 최대 10초 대기
driver.implicitly_wait(10)
Copyfrom selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
wait = WebDriverWait(driver, 10)
# 요소가 클릭 가능할 때까지 대기
element = wait.until(EC.element_to_be_clickable((By.ID, "myButton")))
# 요소가 보일 때까지 대기
element = wait.until(EC.visibility_of_element_located((By.CLASS_NAME, "content")))
Copyimport time
# 3초 대기 (권장하지 않음)
time.sleep(3)
Copy# 전체 페이지 스크린샷
driver.save_screenshot("screenshot.png")
# 특정 요소만 스크린샷
element = driver.find_element(By.ID, "myElement")
element.screenshot("element_screenshot.png")
Copy# 파일 선택 입력 필드에 파일 경로 입력
file_input = driver.find_element(By.TYPE, "file")
file_input.send_keys("/path/to/your/file.pdf")
Copyfrom selenium.webdriver.support.ui import Select
# Select 객체 생성
dropdown = Select(driver.find_element(By.ID, "mySelect"))
# 값으로 선택
dropdown.select_by_value("option1")
# 보이는 텍스트로 선택
dropdown.select_by_visible_text("옵션 1")
# 인덱스로 선택
dropdown.select_by_index(0)
Copyfrom selenium.webdriver.common.alert import Alert
# 알림 대기
alert = WebDriverWait(driver, 10).until(EC.alert_is_present())
# 알림 텍스트 읽기
alert_text = alert.text
print(alert_text)
# 알림 수락
alert.accept()
# 또는 알림 취소
# alert.dismiss()
Copy# 현재 창 핸들 저장
original_window = driver.current_window_handle
# 새 탭 열기
driver.execute_script("window.open('');")
# 새 탭으로 전환
driver.switch_to.window(driver.window_handles[1])
# 새 페이지로 이동
driver.get("https://example.com")
# 원래 탭으로 돌아가기
driver.switch_to.window(original_window)
화면에 브라우저를 띄우지 않고 백그라운드에서 실행:
Copyfrom selenium.webdriver.chrome.options import Options
# Chrome 옵션 설정
chrome_options = Options()
chrome_options.add_argument("--headless") # 헤드리스 모드
chrome_options.add_argument("--no-sandbox")
chrome_options.add_argument("--disable-dev-shm-usage")
# 헤드리스 브라우저 실행
driver = webdriver.Chrome(
service=Service(ChromeDriverManager().install()),
options=chrome_options
)
Copychrome_options = Options()
chrome_options.add_argument("--disable-images") # 이미지 로딩 차단
chrome_options.add_argument("--disable-javascript") # JavaScript 차단
chrome_options.add_experimental_option("prefs", {
"profile.managed_default_content_settings.images": 2
})
Copychrome_options = Options()
chrome_options.add_argument("--page-load-strategy=eager") # DOM 로드 완료 시 즉시 반환
Copy# 세션 단위로 브라우저 재사용
class WebDriver:
def __init__(self):
self.driver = None
def get_driver(self):
if self.driver is None:
self.driver = webdriver.Chrome(
service=Service(ChromeDriverManager().install())
)
return self.driver
def quit(self):
if self.driver:
self.driver.quit()
self.driver = None
Copyfrom selenium.common.exceptions import (
NoSuchElementException,
TimeoutException,
ElementClickInterceptedException
)
try:
element = driver.find_element(By.ID, "myElement")
element.click()
except NoSuchElementException:
print("요소를 찾을 수 없습니다.")
except TimeoutException:
print("시간이 초과되었습니다.")
except ElementClickInterceptedException:
print("요소를 클릭할 수 없습니다.")
except Exception as e:
print(f"예상치 못한 오류: {e}")
Copy# 현재 URL 확인
print(f"현재 URL: {driver.current_url}")
# 페이지 소스 확인
print(driver.page_source)
# 요소 정보 확인
element = driver.find_element(By.ID, "myElement")
print(f"요소 텍스트: {element.text}")
print(f"요소 속성: {element.get_attribute('class')}")
print(f"요소 위치: {element.location}")
print(f"요소 크기: {element.size}")
Copyclass LoginPage:
def __init__(self, driver):
self.driver = driver
self.username_field = (By.NAME, "username")
self.password_field = (By.NAME, "password")
self.login_button = (By.XPATH, "//button[@type='submit']")
def enter_username(self, username):
self.driver.find_element(*self.username_field).send_keys(username)
def enter_password(self, password):
self.driver.find_element(*self.password_field).send_keys(password)
def click_login(self):
self.driver.find_element(*self.login_button).click()
def login(self, username, password):
self.enter_username(username)
self.enter_password(password)
self.click_login()
Copy# config.py
class Config:
IMPLICIT_WAIT = 10
EXPLICIT_WAIT = 10
HEADLESS = False
BROWSER = "chrome"
BASE_URL = "https://example.com"
# 사용
from config import Config
driver.implicitly_wait(Config.IMPLICIT_WAIT)
driver.get(Config.BASE_URL)
Copyimport logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
filename='selenium.log'
)
logger = logging.getLogger(__name__)
try:
driver.get("https://example.com")
logger.info("페이지 로드 성공")
except Exception as e:
logger.error(f"페이지 로드 실패: {e}")
Copyimport csv
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
def scrape_news():
# 브라우저 설정
options = webdriver.ChromeOptions()
options.add_argument("--headless")
driver = webdriver.Chrome(
service=Service(ChromeDriverManager().install()),
options=options
)
news_data = []
try:
# 뉴스 사이트로 이동
driver.get("https://news.example.com")
# 뉴스 기사 목록 대기
wait = WebDriverWait(driver, 10)
articles = wait.until(
EC.presence_of_all_elements_located((By.CLASS_NAME, "news-article"))
)
for article in articles[:10]: # 상위 10개 기사만
try:
title = article.find_element(By.CLASS_NAME, "title").text
summary = article.find_element(By.CLASS_NAME, "summary").text
link = article.find_element(By.TAG_NAME, "a").get_attribute("href")
news_data.append({
"title": title,
"summary": summary,
"link": link
})
except Exception as e:
print(f"기사 처리 중 오류: {e}")
continue
# CSV 파일로 저장
with open("news_data.csv", "w", newline="", encoding="utf-8") as csvfile:
fieldnames = ["title", "summary", "link"]
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
writer.writeheader()
writer.writerows(news_data)
print(f"{len(news_data)}개의 뉴스 기사를 수집했습니다.")
finally:
driver.quit()
# 실행
scrape_news()
Copy# 해결법: 명시적 대기 사용
wait = WebDriverWait(driver, 10)
element = wait.until(EC.presence_of_element_located((By.ID, "myElement")))
Copy# 해결법: 요소가 클릭 가능할 때까지 대기
wait = WebDriverWait(driver, 10)
element = wait.until(EC.element_to_be_clickable((By.ID, "myButton")))
element.click()
Copy# 해결법: 팝업 차단 옵션 추가
chrome_options = Options()
chrome_options.add_argument("--disable-popup-blocking")
chrome_options.add_argument("--disable-notifications")
셀레니움은 웹 자동화의 강력한 도구입니다. 처음에는 복잡해 보일 수 있지만, 기본 개념을 이해하고 꾸준히 연습하면 다양한 웹 작업을 자동화할 수 있습니다.
driver.quit() 호출웹 자동화의 세계는 무궁무진합니다. 셀레니움으로 반복 작업을 자동화하고, 더 창의적인 일에 시간을 투자해보세요! 🚀
참고 자료: