본문 바로가기
카테고리 없음

파이썬 크롤링 동적페이지 셀레니움 요소 못 찾을 때 해결

by heeday4753 2026. 3. 27.

동적 페이지 문제를 해결하려고 Selenium으로 바꿨는데도, 이번에는 find_element에서 바로 막히는 경우가 있습니다. 저도 브라우저는 분명 열렸고 화면에도 요소가 보이는데, 코드에서는 NoSuchElementException이 계속 나와 한동안 선택자만 고쳐 가며 시간을 썼습니다. 알고 보니 선택자 문제가 아니라 로딩 시점, iframe, 동적으로 바뀌는 구조를 제대로 안 본 게 원인이었습니다.

 

 

브라우저에는 보이는데 Selenium은 요소를 못 찾았습니다

 

처음에는 Selenium으로 페이지를 열기만 하면 필요한 값을 바로 잡을 수 있을 줄 알았습니다. driver.get()으로 페이지를 연 뒤 개발자도구에서 본 선택자를 그대로 넣어 find_element(By.CSS_SELECTOR, "...")를 실행했는데, 결과는 예상과 달랐습니다. 화면에는 분명 버튼이나 제목이 보이는데 코드에서는 요소를 찾지 못했고, NoSuchElementException이 반복됐습니다. 이때 가장 먼저 든 생각은 선택자가 틀렸다는 것이었습니다. 그래서 클래스명을 바꾸고, XPath로도 바꾸고, 상위 태그부터 다시 좁혀 보기도 했습니다. 그래도 똑같이 실패했습니다.


문제를 다시 보니 핵심은 "보인다"와 "찾을 수 있다"가 같지 않다는 점이었습니다. Selenium은 브라우저를 열어 주지만, 내가 요소를 찾는 시점에 그 요소가 아직 DOM에 없을 수 있습니다. 특히 동적 페이지에서는 HTML이 처음부터 완성된 상태로 열리지 않고, JavaScript 실행 후 몇 초 뒤에 요소가 추가되기도 합니다. 사람 눈에는 거의 바로 보이지만, 코드 입장에서는 아직 없는 상태인 겁니다. 저도 처음에는 페이지가 열렸으니 로딩이 끝났다고 생각했지만, 실제로는 시각적으로만 보였을 뿐 찾으려는 요소는 뒤늦게 붙는 구조였습니다.


또 하나는 iframe 문제였습니다. 개발자도구에서 분명 보이는 요소인데도 계속 못 찾는 경우가 있었는데, 확인해 보니 해당 영역이 메인 문서가 아니라 iframe 안에 들어 있었습니다. Selenium은 기본적으로 현재 문서 기준으로만 요소를 찾기 때문에, iframe 내부라면 먼저 그 프레임으로 전환해야 합니다. 이걸 모르면 선택자가 100% 맞아도 계속 실패합니다. 결국 이 문제를 겪고 나서야 "선택자가 맞느냐"보다 먼저 "지금 찾는 시점이 맞느냐", "이 요소가 정말 현재 문서 안에 있느냐"를 먼저 보는 습관이 생겼습니다.

 

 

로딩 시점과 iframe을 확인하고 기다리는 방식으로 바꿨습니다

 

문제를 해결할 때 가장 먼저 바꾼 것은 time.sleep()에만 의존하던 방식이었습니다. 처음에는 대기 시간을 2초, 3초, 5초로 늘려 보면서 운 좋게 잡히기를 기대했습니다. 어떤 날은 되고 어떤 날은 또 안 됐습니다. 그래서 무작정 기다리는 대신, "원하는 요소가 실제로 나타날 때까지 기다리는 방식"으로 바꿨습니다. Selenium에서는 WebDriverWait과 expected_conditions를 이용하면 특정 요소가 로드될 때까지 지정 시간 안에서 기다릴 수 있습니다. 이렇게 바꾸고 나니 예전처럼 타이밍 문제로 실패하는 일이 거의 없어졌습니다.

pythonfrom 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

driver = webdriver.Chrome()
driver.get("https://example.com")

wait = WebDriverWait(driver, 10)
title = wait.until(
EC.presence_of_element_located((By.CSS_SELECTOR, ".title"))
)

print(title.text)
driver.quit()

 

이 코드의 핵심은 페이지 전체가 아니라 내가 찾고 싶은 요소를 기준으로 기다린다는 점입니다. 이전처럼 sleep으로 통째로 멈추는 것이 아니라, 요소가 나타나는 즉시 다음 단계로 넘어갈 수 있어 속도와 안정성이 함께 좋아집니다. 특히 목록형 페이지나 검색 결과 페이지처럼 데이터 로딩이 일정하지 않은 환경에서는 이 방식이 훨씬 실용적입니다. "브라우저가 열렸는데 왜 못 찾지"라고 막힌다면, 십중팔구 브라우저가 열린 시점과 요소가 생긴 시점이 달라서입니다.


iframe 문제도 별도로 처리했습니다. 개발자도구에서 요소를 확인할 때 상단에 iframe이 보인다면, Selenium에서도 먼저 해당 프레임으로 이동해야 합니다. 저도 이 부분을 모르고 한참 헤맸는데, 프레임 전환을 넣자 바로 해결됐습니다.

pythonfrom 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

driver = webdriver.Chrome()
driver.get("https://example.com")

wait = WebDriverWait(driver, 10)
wait.until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR, "iframe")))

button = wait.until(
EC.presence_of_element_located((By.CSS_SELECTOR, ".btn"))
)

print(button.text)
driver.quit()

 

이 과정에서 정리한 기준은 명확했습니다. 페이지를 열었는데도 요소를 못 찾는다면, 첫째 로딩이 끝나기 전에 찾고 있는지 봅니다. 둘째 iframe 안 요소인지 확인합니다. 셋째 개발자도구에서 복사한 선택자가 실제 실행 시점에도 유지되는지 다시 봅니다. 넷째 클릭이나 스크롤 이후에 생기는 요소라면 그 동작까지 코드에 넣어야 합니다. 이 순서를 정해 두고 나서는, 무작정 선택자만 바꾸는 일이 없어졌습니다.

 

 

셀레니움에서도 안 잡히는 문제는 대부분 순서 문제였습니다

 

이번 문제를 겪고 나서 가장 크게 느낀 점은, Selenium을 쓴다고 해서 모든 동적 페이지 문제가 자동으로 해결되지는 않는다는 사실입니다. 많은 사람이 requests가 안 되면 Selenium으로 가면 끝이라고 생각하지만, Selenium 안에서도 또 다른 기준이 필요합니다. 화면에 보이는 요소를 사람이 보는 시점과, 코드가 DOM을 탐색하는 시점은 다를 수 있습니다. 여기에 iframe, 클릭 후 생성되는 레이어, 무한 스크롤처럼 변수가 더해지면 단순한 선택자 문제처럼 보여도 실제 원인은 전혀 다를 수 있습니다.


저는 이번 경험 이후로 요소를 못 찾으면 바로 코드를 뜯어고치지 않습니다. 먼저 개발자도구로 해당 요소가 언제 생기는지 보고, iframe 안인지 확인하고, 필요하면 WebDriverWait으로 바꿉니다. 그래도 안 되면 클릭이나 스크롤 이후에만 나타나는 구조인지 확인합니다. 이렇게 순서대로 보면 생각보다 빨리 원인이 나옵니다. 반대로 이 과정을 건너뛰고 XPath만 계속 바꾸면 오히려 시간이 더 오래 걸립니다. Selenium도 결국 순서를 알고 써야 제대로 씁니다.


소개 및 문의 · 개인정보처리방침 · 면책조항

© 2026 블로그 이름