한줄 요약:
로그인 필요한 사이트에서 자동 로그인 → 목록 탐색 → 파일 다운로드까지 한 번에!
Selenium으로 버튼 클릭·입력·스크롤을 자동화하고, 안정적으로 파일을 저장하자.
1. 시나리오 개요
- 로그인 페이지 접속
- 아이디/비밀번호 입력 → 로그인 버튼 클릭
- 다운로드 페이지 이동
- 기간/옵션 선택 → 다운로드 버튼 클릭
- 지정 폴더에 파일 저장 확인
⚠️ 항상 확인! 크롤링/자동화는 사이트 이용약관·로봇정책을 준수해야 하며,
개인 정보/유료 콘텐츠/과도한 요청은 금지입니다.
2. 사전 준비
pip install selenium
- ChromeDriver 설치(버전 맞춤) → 시스템 PATH 또는 프로젝트 폴더에 위치
- 사이트 구조는 크롬 검사(F12) → 셀렉터 복사로 확인
3. 크롬 드라이버(Headless + 자동다운로드) 설정
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
def build_driver(download_dir="downloads", headless=True):
options = Options()
if headless:
options.add_argument("--headless=new")
options.add_argument("--window-size=1400,900")
# 자동 다운로드 폴더 지정
prefs = {
"download.default_directory": download_dir, # 절대경로 권장
"download.prompt_for_download": False,
"download.directory_upgrade": True,
"safebrowsing.enabled": True
}
options.add_experimental_option("prefs", prefs)
driver = webdriver.Chrome(options=options)
return driver
💡 headless=new는 최신 헤드리스 렌더링.
윈도우 경로는C:\\Users\\...\\downloads처럼 절대경로 추천.
🧑💻 1) 자동 로그인 기본 템플릿
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
LOGIN_URL = "https://example.com/login"
def login(driver, user, pw):
driver.get(LOGIN_URL)
# 입력창 로딩 대기
WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, "username"))
)
# 아이디/비번 입력
driver.find_element(By.ID, "username").send_keys(user)
driver.find_element(By.ID, "password").send_keys(pw)
# 로그인 버튼
driver.find_element(By.CSS_SELECTOR, "button.login").click()
# 로그인 성공 신호(프로필/로그아웃 버튼 등) 대기
WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.CSS_SELECTOR, "a.logout, .profile"))
)
print("✅ 로그인 성공")
셀렉터는 사이트마다 다르므로 F12로 확인 후
ID/CSS_SELECTOR/XPATH를 맞춰주세요.
📥 2) 다운로드 페이지 이동 + 옵션 선택 + 다운로드
from selenium.webdriver.common.keys import Keys
import time, os
DOWNLOAD_URL = "https://example.com/report"
def download_report(driver, start_date, end_date):
driver.get(DOWNLOAD_URL)
# 날짜 입력
s = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.ID, "startDate"))
)
s.clear(); s.send_keys(start_date); s.send_keys(Keys.ENTER)
e = driver.find_element(By.ID, "endDate")
e.clear(); e.send_keys(end_date); e.send_keys(Keys.ENTER)
# 옵션(예: CSV) 선택
driver.find_element(By.CSS_SELECTOR, "select#format").click()
driver.find_element(By.CSS_SELECTOR, "select#format option[value='csv']").click()
# 다운로드 클릭
driver.find_element(By.CSS_SELECTOR, "button#download").click()
print("⬇️ 다운로드 요청")
def wait_download_done(folder="downloads", timeout=60):
"""Chrome의 .crdownload 임시파일이 사라질 때까지 대기"""
start = time.time()
while time.time() - start < timeout:
tmp_exists = any(name.endswith(".crdownload") for name in os.listdir(folder))
if not tmp_exists and len(os.listdir(folder)) > 0:
print("✅ 다운로드 완료")
return True
time.sleep(1)
raise TimeoutError("다운로드 대기 초과")
🧩 3) 전체 실행 스크립트
def main():
driver = build_driver(download_dir=os.path.abspath("downloads"), headless=True)
try:
login(driver, user="my_id", pw="my_password")
download_report(driver, start_date="2025-11-01", end_date="2025-11-09")
wait_download_done(folder=os.path.abspath("downloads"), timeout=90)
finally:
driver.quit()
if __name__ == "__main__":
import os
os.makedirs("downloads", exist_ok=True)
main()
4. 동적 요소/지연 로딩 대응 팁
| 상황 | 해결 포인트 |
|---|---|
| 버튼 안 눌림 | element_to_be_clickable 조건으로 대기 |
| 로딩 스피너 | invisibility_of_element_located((By.CSS_SELECTOR,".spinner")) 대기 |
| 무한 스크롤 | execute_script("window.scrollTo(0, document.body.scrollHeight);") 반복 + 대기 |
| 새 창/탭 | driver.switch_to.window(driver.window_handles[-1]) |
5. 로그인 유지(세션/쿠키) 저장하기
반복 실행 시 매번 로그인하면 느려요.
한 번 로그인 후 쿠키를 파일로 저장 → 다음 실행 때 로드하면 빠릅니다.
import json
def save_cookies(driver, path="cookies.json"):
with open(path, "w", encoding="utf-8") as f:
json.dump(driver.get_cookies(), f)
def load_cookies(driver, base_url, path="cookies.json"):
driver.get(base_url)
try:
with open(path, "r", encoding="utf-8") as f:
cookies = json.load(f)
for c in cookies:
driver.add_cookie(c)
driver.refresh()
print("🍪 쿠키 로드 완료")
except FileNotFoundError:
print("쿠키 파일 없음 → 일반 로그인 진행")
일부 사이트는 HttpOnly/도메인 제한/만료 정책으로 쿠키 재사용이 제한될 수 있음.
6. 캡차/2단계 인증(2FA) 대응
| 유형 | 대응 전략 |
|---|---|
| 간단 캡차 | 수동 입력 후 쿠키 저장하여 다음부터 우회 |
| reCAPTCHA v2/3 | 자동화 어려움 → 수동 승인/토큰/공식 API(허용 범위 내) |
| 2FA(OTP/SMS) | 1회 수동 → 세션/리프레시 토큰 재사용 전략 |
중요: 보안 체계 우회는 금지. 합법 범위에서만 자동화.
7. 예외 처리 & 복구 루틴
try:
# 주요 단계...
except Exception as e:
driver.save_screenshot("error.png")
html = driver.page_source
with open("error.html", "w", encoding="utf-8") as f:
f.write(html)
raise
- 실패 시 스크린샷/HTML 덤프 남기면 원인 파악이 빨라요.
8. 체크리스트
- 셀렉터(ID/CSS/XPATH) 최신화
WebDriverWait으로 명시적 대기 적용- headless + 다운로드 폴더 설정 확인
.crdownload소실 확인으로 다운로드 완료 판별- 쿠키 저장/재사용으로 속도 개선
- 약관/법적 이슈 준수
9. 자주 하는 오류 & 해결
| 증상 | 원인 | 해결 |
|---|---|---|
NoSuchElementException | 잘못된 셀렉터/로딩 전 접근 | WebDriverWait + 셀렉터 재확인 |
| 다운로드가 안 됨 | 팝업 차단/권한 | 크롬 prefs로 자동다운로드 허용, 새 탭 전환 처리 |
| 파일 이름이 매번 바뀜 | 서버 타임스탬프/UUID | 폴더 내 가장 최근 파일 탐색 후 리네임 |
| 엑셀 깨짐 | 인코딩/형식오해 | CSV는 utf-8-sig, 엑셀 포맷은 .xlsx로 별도 처리 |
10. 샘플: 최근 파일 찾아 리네임
import glob, time, os, shutil
def move_latest_download(src_dir, dst_path):
files = glob.glob(os.path.join(src_dir, "*"))
latest = max(files, key=os.path.getmtime)
shutil.move(latest, dst_path)
print(f"📦 {os.path.basename(latest)} → {dst_path}")
11. 요약 한 줄
Selenium 매크로로 “로그인 → 조건 선택 → 다운로드 → 저장 확인”까지 자동화하면, 반복 업무가 원클릭으로 끝난다 ✅
이전 강좌 👈 [응용#3] 자동화 프로젝트: 유튜브 인기 영상 데이터 수집기
다음 강좌 👉 [응용#5] 크롤링 + GPT: 텍스트 요약·키워드 추출 자동 리포트 만들기