🔎 selenium로 마우스, 키보드 이벤트를 처리해 특정 사이트 로그인을 해 보자
- 요즈음은
간편 로그인이라는 기능을 지원하는 서비스가 많다.
- 이때 바로 해당 링크로 접속하는 게 아니라 플랫폼에서 로그인을 해야 하는 경우가 많다.
selenium을 통해 자동 로그인이 가능하게 할 수 있다.
naver나 daum 같은 포털 사이트는 이렇게 해도 로그인이 되지는 않고, 2차 인증이 필요하다.
1. 로그인을 위해 필요한 라이브러리 호출
- 로그인을 위해
selenium의 webdriver를 사용해 줄 것이기 때문에 일단 이 라이브러리를 호출한다.
- 우리는 크롬을 사용할 것이기 때문에
ChromeDriverManager 역시 호출해 준다.
마우스 이벤트와 키보드 이벤트를 통해 Action을 취할 것이기 때문에 ActionBuilder와 Keys, ActionChains도 호출해야 한다.
- 또한 특정 요소를 찾아야 하기 때문에
.find_element를 위한 By 라이브러리도 불러와 주어야 한다.
from selenium import webdriver
from selenium.webdriver import ActionChains
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.actions.action_builder import ActionBuilder
from selenium.webdriver import Keys, ActionChains
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
2. 로그인 할 사이트의 요청 보내기
ChromeDriverManager를 사용해 준다.
get을 통해 가지고 온 응답을 바로 읽지 않고 Implicitly Wait를 적용해 준다.
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
driver.get("https://www.naver.com/")
driver.implicitly_wait(0.5)
3. 웹 페이지에서 로그인 버튼의 위치 확인

- 웹 페이지에서
로그인 버튼을 우 클릭 후 검사를 누르면 HTML에서의 로그인 버튼의 위치를 알 수 있다.
로그인 버튼을 지칭하기 위해서는 어떤 요소가 가장 적합한지 확인하는데 현재 로그인 버튼은 ID가 따로 존재하지 않고 class가 존재하므로 class name을 이용해 호출해야 한다는 것을 파악한다.
로그인 버튼을 click 해야 하므로 필요한 이벤트가 click임을 알 수 있다.
4. 로그인 버튼 클릭 구현
- 3번의 과정을 통해
로그인 버튼의 class name이 link_login임을 알 수 있다.
- 종종
class의 이름이 두 개 이상인 경우도 있는데 이는 class의 계층 구조라고 생각하면 된다. 이 경우 호출할 때는 앞의 클래스명.뒤의 클래스명으로 호출해 준다.
.find_element로 button을 찾아 준다.
- 어떠한 이벤트(Action)을 취할 때는
ActionChains을 통해 연쇄적으로 진행할 수 있게 해 준다. ActionChains의 끝에는 .perform()이 있어야 해당 이벤트를 수행할 수 있다.
button = driver.find_element(By.CLASS_NAME, "link_login")
ActionChains(driver).click(button).perform()
5. 로그인 창 분석 
- 버튼을 누른 후 나오는
로그인 창을 분석한다.
로그인 창은 다음과 같이 아이디 입력 칸, 비밀번호 입력 칸, 로그인 버튼이 로그인을 하기 위해 정보임을 알 수 있다.
ID는 고유의 값이므로 ID가 존재한다면 .find_element를 사용할 때 target을 ID로 잡아 줘야 한다.
아이디 입력 칸의 ID는 id이고, 비밀번호 입력 칸의 ID는 pw, 로그인 버튼의 ID는 log.login이다.
6. 아이디와 비밀번호 입력하기
아이디 입력 칸과 비밀번호 입력 칸은 키보드 이벤트를 적용시켜야 한다.
- 먼저 로그인 화면으로 이동하는 버튼을 찾아 준 것과 동일하게
.find_element를 통해 각 input 칸을 찾아 준다.
- 이후
.send_keys_to_element(target, 입력해 줄 값)의 이벤트를 취한다.
- 이때 이벤트들을 연쇄적으로 진행되게 해 주기 위해
ActionChains을 사용한다.
id_input = driver.find_element(By.ID, "id")
ActionChains(driver).send_keys_to_element(id_input, "각자의 아이디").perform()
password_input = driver.find_element(By.ID, "pw")
ActionChains(driver).send_keys_to_element(password_input, "각자의 비밀번호").perform()
7. 로그인 버튼 클릭
login_button = driver.find_element(By.ID, "log.login")
ActionChains(driver).click(login_button).perform()
8. time.sleep 주기
- 이러한 과정이 일련으로 빠르게 일어나다 보면 이벤트 중 하나가 제대로 동작하지 않거나 하는 문제가 발생할 수 있다.
- 그러므로
time 라이브러리를 추가해 주어서 time.sleep(초)를 통해 모션 사이의 임의의 시간을 부여한다.
최종 코드
from selenium import webdriver
from selenium.webdriver import ActionChains
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.actions.action_builder import ActionBuilder
from selenium.webdriver import Keys, ActionChains
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
import time
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
driver.get("https://www.naver.com/")
driver.implicitly_wait(0.5)
button = driver.find_element(By.CLASS_NAME, "link_login")
ActionChains(driver).click(button).perform()
id_input = driver.find_element(By.ID, "id")
ActionChains(driver).send_keys_to_element(id_input, "각자의 아이디").perform()
time.sleep(1)
password_input = driver.find_element(By.ID, "pw")
ActionChains(driver).send_keys_to_element(password_input, "각자의 비밀번호").perform()
time.sleep(1)
login_button = driver.find_element(By.ID, "log.login")
ActionChains(driver).click(login_button).perform()
time.sleep(1)