본문 바로가기
파이썬코드공유

파이썬 셀레니움 ElementClickInterceptedException 해결방법

by 하이어시스템 2023. 10. 12.
반응형

파이썬에서 버튼의 클릭 또는 텍스트 입력을 위해서는 웹 엘리먼트를 클릭해야 합니다. 하지만 구글 애드센스 광고나 기타 엘리먼트들에 의해서 대상 엘리먼트가 가려지는 원인으로 ElementClickInterceptedException 예외가 발생하는 경우가 빈번합니다. 이 글에서는 ElementClickInterceptedException이 발생했을 경우 조치하는 방법에 대해서 알아보겠습니다.

ElementClickInterceptedException

 

1. 엘리먼트가 Clickable 할 때 까지 대기하기

웹 서버가 웹페이지(html, javascript, css)를 만들어 내고 이를 물리적인 인터넷이라는 공간을 통해 클라이언트의 PC로 전송하여 웹 브라우저가 파싱하여 화면에 보여주기까지에는 충분한 대기시간이 필요합니다. 셀레니움에서는 2단계로 구분하고 있습니다. 이것은 presence_of_element_located와 element_to_be_clickable 2가지 입니다. 만약 엘리먼트를 클릭을 해야 한다면 클릭가능한(clickable) 상태까지 대기해야 하는데요, 이것은 아래와 같이 코드를 작성할 수 있습니다.

ignored_exceptions=(NoSuchElementException, StaleElementReferenceException)
element = WebDriverWait(start_element, time_out, ignored_exceptions=ignored_exceptions).until(ec.element_to_be_clickable((By.ID, id_name)))

위의 코드에서 ignored_exceptions는 엘리먼트가 클릭가능한(clickable) 상태가 될 때 까지 대기하면서 해당 예외가 발생할 경우 무시하도록 하는 것입니다. 클라이언트의 웹 브라우저가 웹 페이지를 모두 로드하지 못한 경우에는 발생할 수 있는 예외들이므로 무시하는것이 좋습니다. 그리고 By.ID, id_name는 By.CLASS_NAME, class_name 와 By.XPATH, xpath등으로 변경할 수 있습니다.

 

2. 엘리먼트를 클릭 가능한 영역으로 노출 시키기

엘리먼트가 브라우저의 보이지 않는 영역에 있다면 클릭이 불가능한 경우가 많습니다. 엘리먼트를 화면의 보이는 영역으로 이동시키는 방법은 다양합니다. 웹 사이트의 특성에 따라서 작동되는 코드를 활용하면 됩니다.

 

1)웹 엘리먼트의 기본 속성 이용하기

아래의 코드를 이용해서 웹 엘리먼트를 화면의 보이는 영역에 노출시킬 수 있습니다.

element.location_once_scrolled_into_view

 

2)ActionChains을 이용한 엘리먼트 화면 노출

ActionChains는 셀레니움에서 이벤트를 좀 더 확실하게 발생시켜 주는 클래스로서 활용빈도가 높습니다. 엘리먼트를 화면에 노출시킬때도 사용할 수 있습니다.

action = ActionChains(self.browser)
action.move_to_element(element).perform()
action.reset_actions()

 

3)Javascript 활용하기

만약 ActionChains으로 엘리먼트 위치를 이동시킬 수 없다면 웹 페이지를 좀 더 강력하게 통제할 수 있는 Javascript를 고려해 볼 수 있습니다.

link_element_y_pos = link_element.location['y']
driver.execute_script("window.scrollTo(0, arguments[0]);", link_element_y_pos)

만약 해당 element가 id를 가지고 있다면 다음과 같이 간결하고 강제화된 클릭을 유도할 수 있다.

driver.execute_script('document.getElementById("mf_alCmInfo").click();')

 

4)화면 중심으로 위치시키기

엘리먼트를 화면의 보이는 영역으로 이동하였으나 보통 화면 보이는 영역의 상단 또는 하단에 위치시키는 경우가 대부분입니다. 이런 경우 페이지 상단 또는 하단의 다른 엘리먼트에 가려져 클릭이 불가능한 경우가 있습니다. 아래의 그림을 보시면 이해가 되실 겁니다. 이런 경우에는 엘리먼트를 화면의 중심으로 배치시키는 방법을 검토해 볼 수 있습니다.

페이지 상단 및 페이지 하단의 가려지는 영역

element_y_pos = link_element.location['y']
monitor_height = self.browser.execute_script("return window.screen.availHeight;")/2
driver.execute_script("window.scrollTo(0, arguments[0]);", element_y_pos-monitor_height)

위의 코드에서 screen 객체의 속성은 아래와 같습니다.
screen.width : 화면(모니터 해상도)의 너비
screen.availWidth : 모니터 화면의 작업 표시줄을 제외한 너비
screen.height : 화면(모니터 해상도)의 높이
screen.availHeight : 모니터 화면의 작업 표시줄을 제외한 높이

 

5)내부 스크롤에 숨겨져 있는 엘리먼트 노출 시키기

웹 페이지 전체가 아닌 일부 영역이 스크롤로 리스트가 보여지고 있고, 클릭하고자 하는 엘리먼트가 현재 노출되어 있지 않다면 자동으로 스크롤 노출 영역으로 나타나게 할 수 있습니다.

driver.execute_script("arguments[0].scrollIntoView(true);", element)

 

6)Custom Code

만약 위와 같은 방법으로도 엘리먼트가 화면의 보이는 영역에 노출되지 않는다면 스크롤바의 위쪽 클릭 버튼과 아래쪽 클릭 버튼을 이용하는 방법, 엘리먼트의 x, y 좌표등을 를 읽어 원하는 위치에 노출시키는 방법을 고려해 볼 수 있습니다. 이 경우는 코드 개발에 상당한 노력이 필요하게 됩니다. 물론 하이어시스템에서는 어떤 경우에도 화면에 노출시켜 클릭하는 개발기술을 보유하고 있습니다.

 

3. 엘리먼트 클릭하기

일반적으로 웹 엘리먼트는 click()이라는 메서드를 가지고 있으나 click()이 경우에 따라 작동되지 않을 수 있습니다. 이런 경우 다음과 같은 우회처리를 고려해 볼 수 있습니다.

 

1)ActionChains를 이용한 click 강제화

ActionChains를 이용하면 좀 더 강제화된 click()을 발생시킬 수 있습니다. 웹 엘리먼트의 click()이 작동되지 않는 경우 최 우선적으로 검토해 보세요.

action = ActionChains(self.browser)
action.click(element).perform()
action.reset_actions()

 

2)Javascript를 이용해서 click하기

Javascript 역시 좀 더 강력하게 클릭을 유도하는 방법입니다. 아래와 같이 적용할 수 있습니다.

driver.execute_script("arguments[0].click();", element)

 

3)이미지로 찾아서 클릭하기

Worst Case로 canvas 와 같은 태그로 클릭 대상이 이미지화 되어 있는 경우를 만날 수 있습니다. 이런 경우에는 셀레니움을 이용할 수 없고 pyautogui를 이용하여 미리 저장된 이미지와 같은 영역을 찾아 클릭하도록 코드를 작성해야 합니다.

pyautogui.locateOnScreen('image_name.png', confidence=0.8)
if location is not None:
    center_x, center_y = pyautogui.center(location)                
    pyautogui.moveTo(center_x, center_y)
    pyautogui.click(center_x, center_y)

 

반응형