Selenium은 브라우저를 직접 제어해야 할 때 쓰는 도구다.
클릭이 필요하거나, 자바스크립트로 렌더링된 요소를 읽어야 하거나, 페이지 이동 후 DOM이 바뀌는 구조라면 requests보다 Selenium이 더 맞다.
핵심은 네 가지다. 요소 찾기, 값 가져오기, 반복 구조 만들기, 대기 처리.
1. Selenium 기본 흐름
흐름은 단순하다.
- 드라이버 실행
- URL 접속
- 요소 찾기
- 텍스트나 속성값 추출
- 클릭 후 대기
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
path = "/Users/yourname/path/to/chromedriver"
service = Service(path)
driver = webdriver.Chrome(service=service)
driver.get("<https://example.com>")
2. 요소 찾기: find_element()와 find_elements()
find_element()는 하나, find_elements()는 여러 개를 찾는다.
from selenium.webdriver.common.by import By
title = driver.find_element(By.XPATH, '//*[@id="title"]')
items = driver.find_elements(By.CSS_SELECTOR, ".item")
- 버튼 1개, 제목 1개 → find_element()
- 목록, 카드, 행 여러 개 → find_elements()
목록형 페이지는 결국 이 둘을 계속 조합해서 쓴다.
3. XPATH는 “정확한 경로”보다 “반복 가능한 구조”가 중요하다
Selenium에서 XPATH를 복붙만 하면 처음엔 되지만, 반복문으로 가면 금방 불편해진다.
목록형 페이지에서는 행 번호만 바뀌는 구조로 잡는 게 훨씬 낫다.
for i in range(1, 6):
path = f'//*[@id="listTable"]/tbody/tr[{i}]/td[1]'
print(driver.find_element(By.XPATH, path).text)
중요한 건 tr[{i}]처럼 반복 가능한 패턴이다. 즉 XPATH는 길게 찾는 기술보다, 반복문에 들어갈 수 있게 만드는 기술이 더 중요하다.
4. .text와 get_attribute() 차이
이건 Selenium에서 제일 많이 헷갈린다.
.text
화면에 보이는 텍스트를 가져온다.
name = driver.find_element(By.XPATH, some_path).text
get_attribute()
태그 안의 속성값을 가져온다.
href = driver.find_element(By.XPATH, some_path).get_attribute("href")
title = driver.find_element(By.XPATH, some_path).get_attribute("title")
정리하면 이렇다.
- 화면에 보이는 값 → .text
- 링크 주소, title, src 같은 값 → get_attribute()
5. 클릭 후에는 바로 읽지 말고 기다려야 한다
클릭이 됐다고 바로 다음 DOM이 준비된 건 아니다.
그래서 페이지 이동이나 탭 전환이 있으면 대기 처리가 필요하다.
가장 쉬운 방법은 sleep이다.
import time
driver.find_element(By.XPATH, next_path).click()
time.sleep(3)
실습 단계에선 충분하지만, 실제 반복 수집 코드에선 명시적 대기가 더 낫다.
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver.find_element(By.XPATH, next_path).click()
WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.XPATH, '//*[@id="listTable"]/tbody/tr[1]/td[1]'))
)
즉 Selenium에서 안정성은 대기 처리에서 갈린다.
6. 실전에서 자주 쓰는 패턴
실제로는 아래 조합이 제일 많이 나온다.
- find_element() / find_elements()
- By.XPATH 또는 By.CSS_SELECTOR
- .text
- get_attribute("href")
- click()
- WebDriverWait
이 패턴만 익혀도
게시판, 상품 목록, 뉴스 리스트, 공시 페이지 같은 목록형 웹페이지 크롤링은 거의 같은 구조로 응용할 수 있다.
7. DART 공시 페이지에 적용하면
DART 공시 목록도 결국 같은 패턴이다.
날짜로 URL 만들고, 목록의 tr[i]를 반복하면서 공시 시간은 .text, 링크 주소는 get_attribute("href")로 가져오면 된다.
import datetime
from selenium.webdriver.common.by import By
date = datetime.datetime(2026, 4, 16).strftime("%Y.%m.%d")
url = f"<https://dart.fss.or.kr/dsac001/mainAll.do?selectDate={date}¤tPage=1>"
driver.get(url)
for i in range(1, 6):
path = f'//*[@id="listContents"]/div[2]/table/tbody/tr[{i}]/td[1]'
print(driver.find_element(By.XPATH, path).text)
중요한 건 DART 자체보다,
반복 가능한 XPATH + .text/get_attribute() 구분 + 대기 처리라는 Selenium 기본기다.
Selenium은 사이트별 꼼수보다 요소 찾기, 값 추출, 반복 구조, 대기 처리 네 가지 패턴을 먼저 익히는 게 중요하다.
'Data Analytics > 수집·크롤링' 카테고리의 다른 글
| JSON 응답을 Pandas DataFrame으로 정리하는 방법 | 리스트와 딕셔너리 두 방식 비교 (0) | 2026.05.13 |
|---|---|
| API 데이터 수집할 때 샘플 단위로 처리해야 하는 이유 | 열 단위 수집이 위험한 이유 (0) | 2026.05.08 |
| BeautifulSoup HTML 파싱 정리 | 일반 웹사이트에서 태그와 속성으로 데이터 추출하는 방법 (1) | 2026.05.08 |
| BeautifulSoup XML 파싱 정리 | find와 find_all 차이부터 영화 정보 추출까지 (0) | 2026.05.08 |
| JSON과 XML 차이 정리 | API 응답 포맷에 따라 파이썬 처리 방식이 달라지는 이유 (0) | 2026.05.07 |
