동행복권 사이트 로그인 기능을 만들어 보려합니다. 로그인 과정에 필요한 기능은 간단하게 아래와 같습니다.
- 버튼 클릭 기능
- input 에 텍스트 입력 기능
로그인 단계를 selenium 동작 단계로 보면 아래와 같습니다.
- 메인페이지에서 로그인 버튼 찾기
- 로그인 버튼 클릭
- 아이디 input 찾기
- 아이디 입력
- 비밀번호 input 찾기
- 비밀번호 입력
- 엔터키 입력
위 작업은 간단하기 때문에 사전에 필요한 작업을 먼저 하겠습니다.
1. python-dotenv 설치
pip install python-dotenv
python-dotenv 의 역할은 .env 파일을 읽어올 수 있게 합니다.
2. 클릭 함수 작성
def click(element):
element.click()
element 를 넘겨주면 클릭하는 함수입니다.
3. 문자 입력 함수 작성
def send_keys(element, text):
element.send_keys(text)
처음 보면 생소할 수 있지만 selenium 에서는 send_keys 를 사용하여 문자를 입력합니다.
4. 환경 변수 읽어오기
from dotenv import load_dotenv
import os
load_dotenv()
.env 파일을 만들어서 관리하는 이유는 이 프로젝트가 private repository 이면 상관이 크게 없을 수 있지만 public 하면 .env 로 계정 정보를 나만 알 수 있도록 관리하는 것이 필요합니다. 또한 때에 따라 다를 수 있지만 .env 에 중요한 계정 정보나 키를 넣어 놓게 되면 관리에 유용하기에 환경 변수 파일을 자주 생성해서 관리합니다. .env 파일은 KEY=VALUE 형식으로 ID=FOO 라고 입력하면 os.environ.get(‘ID’) 의 출력 결과는 FOO 가 나오게 됩니다.
print(os.environ.get('ID')) #FOO
5. 메인페이지에서 로그인 버튼 찾기
크롬 개발자 도구를 통해 로그인 버튼을 찾고 xpath 를 복사하였습니다.
6. 로그인 버튼 클릭
5번 과정에서 복사한 xpath 를 이용하여 버튼 코드를 작성합니다.
click(driver.find_element(By.XPATH, '/html/body/div[1]/header/div[2]/div[2]/form/div/ul/li[1]/a'))
find_element에서 쓰인 By 의 경우는 selenium 에서 제공합니다. 불과 몇달 전만해도 find_element_by_id 등으로 사용했지만 By 를 사용하여 element 를 찾는 함수를 하나로 줄일려고 하는 것 같습니다.
7. 아이디 input 찾기
아이디 input 의 경우는 #userId 로 id 가 존재하는 것을 확인했습니다.
8. 아이디 입력
send_keys(driver.find_element(By.ID, 'userId'), os.environ.get('ID'))
9. 비밀번호 input 찾기
비밀번호 input 의 경우는 id 가 없어서 name 을 가지고 찾아야할 것 같습니다.
10. 비밀번호 입력
비밀번호의 경우 id 가 없기 때문에 name 으로 찾겠습니다.
send_keys(driver.find_element(By.NAME, 'password'), os.environ.get('PW'))
11. 엔터키 입력
로그인 버튼을 찾아서 클릭해도 되지만 다양한 상황을 적고 싶어서 엔터키를 입력하는 방식을 선택하였습니다. 엔터키하면 다른 selenium 의 기능이 쓰일 것 같지만 그렇지 않고 send_keys 로 처리가 됩니다. By 처럼 selenium 에서 제공하는 Keys 를 사용하면 됩니다.
send_keys(driver.find_element(By.NAME, 'password'), Keys.ENTER)
유의할 점은 엔터를 입력한다는 것은 특정 element 에 엔터키를 입력한다는 것 입니다. 만약 비밀번호 input 에 엔터를 입력하는 것이 아니라 다른 영역에 엔터키를 입력하면 아무 반응이 일어나지 않을 것 입니다. 이처럼 어떤 곳에 엔터키를 입력할 것인지 확인해야합니다.
전체 코드
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from dotenv import load_dotenv
import os
load_dotenv()
def create_driver():
return webdriver.Chrome(service=Service('./driver/chromedriver_mac64_m1_97'))
driver = create_driver()
driver.get('https://dhlottery.co.kr/common.do?method=main')
def get_main_handle(main_url):
for window_handle in driver.window_handles:
driver.switch_to.window(window_handle)
print(f'현재 핸들러 name : {driver.current_window_handle}')
print(f'현재 url : {driver.current_url}')
print('')
if main_url in driver.current_url:
return window_handle
raise '메인 핸들러 찾지 못함'
def close_windows_if_not_main_url(main_url):
main_handle = get_main_handle(main_url)
for window_handle in driver.window_handles:
if main_handle != window_handle:
driver.switch_to.window(window_handle)
driver.close()
driver.switch_to.window(main_handle)
def send_keys(element, text):
element.send_keys(text)
def click(element):
element.click()
close_windows_if_not_main_url('common.do?method=main')
click(driver.find_element(By.XPATH, '/html/body/div[1]/header/div[2]/div[2]/form/div/ul/li[1]/a'))
send_keys(driver.find_element(By.ID, 'userId'), os.environ.get('ID'))
send_keys(driver.find_element(By.NAME, 'password'), os.environ.get('PW'))
send_keys(driver.find_element(By.NAME, 'password'), Keys.ENTER)