Qoo10 리뷰 크롤링 시 페이징 버튼이 화면에 표시되지 않는 문제 때문에 기존의 시각적 버튼 클릭 방식 대신 다른 접근 방식을 사용했다.
공부의 축복이 끝이 없어 ~~!!!!!!!
대부분의 웹 크롤링 튜토리얼에서는 find_element
로 "다음" 버튼을 찾아 click()
하는 방식으로 페이징을 처리한다.
하지만, 특정 웹사이트(예: Qoo10 리뷰 페이지)에서는 총 리뷰 개수는 많은데도 불구하고, 페이지 하단의 "1, 2, 3, 다음"과 같은 페이징 UI 요소가 아예 HTML에 렌더링되지 않는 문제가 발생할 수 있다.
이는 서버 응답 오류, JavaScript 로딩 실패, 또는 특정 조건(예: 검색 결과 없음)에 따른 의도된 동작일 수 있다고 한다.
이러한 상황에서는 WebDriverWait
으로 next_button
을 아무리 기다려도 찾을 수 없으므로, 기존 방식으로는 다음 페이지로 넘어갈 수 없다 ㅠㅠ
((개발이 빨리 끝날 줄 알았지만 ... 페이징이 안뜨는 이슈를 못찾아서 삽질만 왕창 ..))
페이징 UI가 없더라도, 웹사이트는 다음 페이지의 데이터를 어딘가에서 가져와야 한다. 이는 주로 AJAX(Asynchronous JavaScript and XML) 통신을 통해 이루어진다!!
Qoo10 리뷰 페이지의 경우, HTML 소스코드나 JavaScript 이벤트 리스너를 분석해보면 javascript:opinionList(페이지번호);
와 같은 JavaScript 함수 호출이 다음 페이지 로드를 담당한다는 것을 확인할 수 있었다.
<a href="#" onclick="javascript:opinionList(2); return false;">2</a>
Selenium WebDriver는 브라우저의 JavaScript 환경에서 임의의 JavaScript 코드를 실행할 수 있는 driver.execute_script()
메서드를 제공한다.
이 메서드를 활용하여, 웹사이트 내부적으로 다음 페이지를 로드하는 데 사용되는 JavaScript 함수(opinionList()
)를 우리가 직접 호출하는 방식으로 페이지를 이동시킬 수 있다.
driver.execute_script(f"javascript:opinionList({target_page});")
이 방식은 브라우저가 화면에 특정 요소를 렌더링하기를 기다릴 필요 없이, 필요한 액션을 직접 지시하는 방법이다.
opinion_count
) 확인:math.ceil(total_reviews / 10)
).execute_script
호출:while
루프 내에서 현재 page
번호에 1
을 더한 target_page
를 인자로 opinionList()
함수를 호출한다.driver.execute_script(f"javascript:opinionList({target_page});")
time.sleep(2)
).WebDriverWait
을 사용하여 새로운 리뷰 엘리먼트가 로드될 때까지 기다리거나, 이전 페이지의 리뷰 엘리먼트가 사라지는 것(EC.staleness_of
)을 기다린다.last_review_text_on_previous_page
변수를 사용하여, execute_script
를 호출했음에도 불구하고 다음 페이지의 첫 번째 리뷰 내용이 이전 페이지의 마지막 리뷰 내용과 동일하다면, 더 이상 새로운 콘텐츠가 없다고 판단하고 크롤링을 종료한다.ABSOLUTE_MAX_PAGES
(예: 500페이지) 제한을 두어, 혹시 모를 로직 오류나 웹사이트의 비정상적인 동작으로 인한 무한 루프를 방지한다.finally
블록을 통한 WebDriver 종료:try...except
블록 바깥의 finally
블록에서 driver.quit()
을 호출하여 크롤링 성공 여부나 오류 발생 여부와 상관없이 항상 WebDriver(브라우저)를 깔끔하게 종료하고 리소스를 해제한다. 크롤러의 안정성과 시스템 리소스 관리에 매우 중요하다.execute_script
는 웹사이트의 원래 동작 방식과 다를 수 있으며 문제가 발생할 수도 있다.