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

Selenium ActionChains - 보다 확실한 동작 수행이 필요할 때

by 하이어시스템 2023. 9. 2.
반응형

하이어시스템 소개

 

하이어시스템 소개 feat.김프로

소개 안녕하세요, 저는 하이어시스템의 김프로입니다. 여러분들이 어려움을 겪고 계신 일상 업무를 저의 안정적이고 빠른 소프트웨어로 자동화하는 것, 그것이 저의 목표입니다. '하이어시스템

wise-office-worker.tistory.com

Selenium을 사용하여 웹 자동화를 개발할 때 WebElement의 click(), send_keys()등의 메서드가 작동하지 않을 때 ActionChains을 사용하여 해결되는 경우가 많습니다. 이번 포스팅에서는 ActionChains에 대해서 알아보겠습니다.

 

아래의 코드는 정확하게 같은 자동화 동작을 하지만 다른방식으로 구현한 코드입니다.

 

1. WebElement

price_element = self.browser.find_element_by_id('description')
            
price_element.click()
time.sleep(1)
price_element.send_keys("test입니다")
time.sleep(1)

 

2. ActionChains

price_element = self.browser.find_element_by_id('description')

ac = ActionChains(self.browser)
ac.click(price_element).send_keys("test입니다").perform()
ac.reset_actions()
time.sleep(1)

코드설명 : ActionChains의 인스턴스 ac를 생성하고 queue에 click, send_keys등 연속적으로 일어날 자동화 동작을 지정합니다. 마지막에 perform() 메서드를 호출하면 queue에 입력된 명령들이 순서대로 실행됩니다. 묶음의 동작을 마치면 reset_action() 해주는것이 좋습니다. 아래쪽에서 다시 ActionChains 메서드를 이용할 경우 동작이 안되는 경우가 있을 수 있습니다.

 

일반적인 사이트에서 위의 1과 2는 모두 동작합니다. 하지만 1번이 동작하지 않는 사이트에서는 2번 방식으로 우회가 되는 경우가 많습니다. 그렇다면  ActionChains는 왜 성능이 뛰어날까요?

 

https://selenium-python.readthedocs.io/api.html#module-selenium.webdriver.common.action_chains

 

자세한 설명은 홈페이지에서 찾을 수 없었지만 위의 설명에서 "low level interactions" 란 문구가 눈에 띕니다. 실제로 코드를 구현해보면 웹엘리먼트의 click()의 경우 다른 엘리먼트에 의해 가려진 경우에는 막히지만(blocking) Action Chains의 경우 논리적으로는 다른 엘리먼트에 의해 가려지 있다고 할지라도 화면상에서 클릭 가능하다면 다른 조건을 무시하고 클릭을 수행합니다. 굳이 설명하자만 논리적 조건까지 맞을때만 WebElement의 메서드는 작동하지만, Action Chains의 경우에는 물리적인 조건만 만족하면 해당 위치에 클릭을 실행시킨다고 생각하면 되겠습니다.

 

그럼 Action Chain을 무조건 사용하는게 좋을까요?

대다수의 click과 대다수의 send_keys는 웹 엘리먼트이 기능이 잘 작동됩니다. 그러므로 굳이 코드를 많이 사용해가며 Action Chain을 쓸 필요는 없습니다. 필요한경우에 우회하는 방법으로 사용하면 좋을것 같습니다.

 

Action Chain의 메서드를 알아보겠습니다.

자주 사용하는 메서드는 다음과 같습니다. click, move_to_element, send_keys

https://www.geeksforgeeks.org/action-chains-in-selenium-python/?ref=lbp

 

주의사항

ActionChains의 send_keys 에서 조합키를 사용할때는 아래와 같은 방법으로 사용해야 합니다.

ac = ActionChains(self.browser)
ac.key_down(Keys.CONTROL).send_keys('a').key_up(Keys.CONTROL).perform()
ac.reset_actions()

 

반응형