본문 바로가기
Programming/Python

[Python] 파이썬으로 크롤링하기 / 웹 데이터 추출 / 업무자동화 - 3. Selenium 활용 및 브라우저 제어 / ActionChains

by EunjiBest 2022. 5. 20.

[Python] 파이썬으로 크롤링하기 / 웹 데이터 추출 / 업무자동화 - 3. Selenium 활용 및 브라우저 제어/ ActionChains

 

 

 

Selenium에서 브라우저 제어가 필요한 이유.

 

앞선 포스팅에서 selenium으로 요소를 불러오고 정보를 뽑아오는 문법들을 간단히 알아보았다.

정보를 이렇게 쉽게 모을 수 있다면 좋을테지만,

그렇게 호락호락한 웹 세상이 아니라는 점!

 

브라우저 제어가 따로 필요한 상황을 알아보자.

 

1. 로그인이 필요한 경우(ex. 내 메일함의 받은 메일 제목을 추출)

-> 로그인 자동화 필요 (아이디입력 -> 비밀번호입력 ->로그인 버튼 클릭하기)

 

2. 동적으로 렌더링되는 페이지( ex. 드랍다운 버튼을 클릭해야 html 요소가 나타나는 경우)

-> 드랍다운 버튼을 클릭해주는 자동화 기능 필요 (드랍다운 버튼찾기 -> 버튼 클릭하기)

 

기타 등등

웹에는 예상치 못한 변수들이 조금씩 존재한다.

 

하지만 걱정할 필요가 없다!

바로 Selenium은 크롤링에 최적화된 툴이기 때문에 이러한 문제들을 간단히 해결해줄 수 있는

브라우저 제어 기능이있다.

 

 

 

 

 

 

브라우저 로딩 기다리기

 

가끔 웹페이지 서버문제나 집 인터넷 연결 문제 등의 다양한 네트워크 문제로인해

웹 페이지의 로딩이 일정 기준이상 느릴경우,

driver.find_element()에서 에러가 날 수 있다.

 

따라서, 웹페이지가 로딩되는 시간에 약간의 여유를 줄 필요가 있다.

 

이 문제는 간단한 코드로 해결을 할 수 있는데

총 3가지의 방법이 있다.

 

 

1. 무조건 기다리게하기

 

time.sleep(n)

 

-> n초만큼 기다리겠다는 명령을 입력하고 기다린다.

-> 파이썬 자체의 내장 라이브러리이다. (import time 필요) 

-> n초 이내에 로딩이 끝났어도 n초가 될 때까지 기다려야한다.

-> 따라서 시간상 비효율적이다.

 

 

 

2. 암시적 기다리게하기

 

driver.implicitly_wait(n)

 

-> selenium 함수이다.

-> 웹 페이지를 새로 로딩 할 때마다 최대 n초까지 기다린다.

-> 웹 페이지의 로딩이 끝나면 기다리기를 종료하고 코드를 수행한다.

-> 한 번만 설정을 해주면 계속해서 적용이 된다.

 

 

 

3. 명시적 기다리게하기

 

웹페이지는 로딩이 되었는데, 원하는 요소는 불러와지지 않는 경우가 있다.

특정 요소가 로딩이 지연되는 경우가 종종있기 때문이다.

 

말이 어렵지만, 일상생활에서 생각을 해보면

실제로 인터넷을 할 때 웹페이지 로딩은 끝났지만 용량이 큰 이미지나, 영상들이 늦게 보여지는 경우를 경험했을 것이다.

대부분이 이런 요소들은 javascript를 이용해 기능이 들어가있는 요소일 확률이 높다.

 

3번째 방법은 기다릴 요소를 명시하고 기다리게 한다.

 

먼저 불러와야하는 함수들이 조금있다!

 

from 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

 

간단하게 이정도..?ㅎ

 

WebDriverWait(driver,n).until(EC.presence_of_element_located((By.ID, "id_name"))

 

-> 기다릴 요소를 명시하고

-> 명시된 요소가 해당 방식으로 불러와질 때까지 최대 n초를 기다린다.

-> 요소는 class_name, xpath등으로 찾을 수 있다.

 

presence_of_element_located를 쓰게 되면, 괄호 안의 요소가 나타날 때까지 기다린다.

뒤에 붙는 ((By.ID, "id_name")) 이 경우는 튜플 형태로 들어간다.

요소를 찾는 방법과 파라미터를 의미한다. 위 코드는 id를 아이디 이름으로 찾는다. 이런뜻이다.

그 외 (By.XPATH, "xpath") -> xpath형식으로 찾는다던지 , (By.CLASS, "class_name") ->클래스 이름으로 찾는다던지등

다양한 옵션들이 있다.

 

element_to_be_clickable

위 함수는 해당 요소가 클릭 가능해질 때까지 기다리는 함수이다. (이름이 매우 직관적이다)

비활성화 버튼이 활성화가 되면 눌리게 할 때 자주 쓰이는 함수이다.

 

 

 

 

키보드 및 마우스 제어_입력자동화

 

키보드와 마우스 입력으로 로그인을 자동화해보자.

 

 

1. 키보드입력

 

send_keys('my_id' + Keys.ENTER)

 

send_keys

-> 해당 요소에 나열된 key sequence를 순차적으로 입력한다.

-> 위 코드에서는 m -> y -> _ -> i -> d를 순서대로 입력한다.

 

Keys

-> 특수 키를 쓸 수 있게 해주는 class이다.

-> 위 코드에서는 ENTER를 입력하라는 뜻이다.

(ENTER, CONTROL,SHIFT)등 다양한 키를 입력할 수 있고 항상 대문자로 입력해야한다.

 

 

2. 마우스입력

 

.click()

 

.click()

-> 해당 요소를 클릭하게 해주는 함수이다.

 

 

 

 

ActionChains

 

위에서 했던 기본적인 행동 말고,

더블 클릭이나, 컨트롤 클릭 등 더 복잡한 동작을 자동화 시켜보자.

 

ActionChains을 통해 다음과 같은 기능들을 할 수 있다.

이름그래로 Action을 여러개 묶어서 다양한 동작을 수행할 수 있도록 해준다.

 

chains = webdriver.ActionChains(driver)

chains.action1()
chains.action2()
chains.action3()
chains.action4()
.
.
.
chains.perform()

 

action을 여러개 수행한 뒤, perform을 통해 닫으면

하나의 actionchain이 생성된다.

 

 

1. send_keys_to_element

 

chains.send_keys_to_element(id, 'my_id')

-> 주어진 요소(위 코드에서 id)에 주어진 key sequence를 입력한다(위 코드에서는 my_id)

-> 하나의 ActionChains내에서 여러 요소 액션을 수행할 수 있다.

 

 

 

2. send_keys

 

chains.send_keys(Keys.ENTER)

 

-> send_keys의 경우에는 요소가 주어지지 않아서 현재 커서가 위치한 곳에서 key sequence가 입력된다.

-> 위 코드에서는 현재 커서가 위치한 곳에서 ENTER를 입력해라는 뜻이다.

 

 

그럼 이제 다양한 action을 합쳐보자.

 

 

3. 컨트롤 + click

 

chain.key_down(Keys.CONTROL)
chain.click('버튼요소')
chain.perform()

 

위에서 사용했던 함수들만으로 이런 ActionChains를 할 수 있다.

마지막은 꼭

.perform()으로 닫아주는 것을 잊지말자.

 

 

 

4. 마우스 커서를 올렸다가 3초뒤에 떼기

 

chain.move_to_element('버튼요소')
chain.pause(n)
chain.move_by_offset(x,y)
chain.perform()

 

 

chain.move_to_element
-> 주어진 요소로 마우스 커서이동
 
pause
-> n초만큼 멈췄다가 뒤의 액션을 수행
 
move_by_offset
-> x,y축으로 주어진 수치만큼 이동한다.

 

이러한 다양한 메서드를 알아두고 원하는 조합을 할 수 있다면,

자동화하는 것은 어렵지 않을 것이다.

(다행히, 메서드의 이름들이 직관적이라 외우기 어렵지 않다)

 

 

 

 

 

 

 

 

 

반응형

댓글