[Selenium] Selenium 을 이용하여 복권 구매 자동화 만들어보기 #4
이전 글에서 로그인 기능을 만들어 보았습니다. 이번 글에서는 복권 구매까지 진행을 해보겠습니다. 다음글에서는 마지막 코드 리펙토링을 진행하도록 하겠습니다.
이 글을 끝에 구매 버튼이 있는데 진짜로 구매하시려면 예치금을 충전하시면 가능합니다.
복권 구매는 단계를 나누어 보면 아래와 같습니다.
1. 메인 페이지에서 복권 구매 버튼 클릭(클릭 시 팝업 열림)
2. 복권 구매 번호 랜덤으로 발행(자동번호 발행 기능이 이미 있지만 코드 예제를 위해 수동으로 진행)
3. 구매 버튼 클릭
단계를 나누어보면 새로 배울 개념이 없지만 여기서 문제라고하면 복권 구매 화면이 iframe 형식으로 구성이 되어있다는 것입니다. iframe 으로 되어있는 경우 selenium 을 통해 현재 frame 을 이동시켜줘야 원하는 element 등에 접근 가능합니다.
우선 몇 개의 함수를 먼저 작성하겠습니다.
script 실행하기
def execute_script(script):driver.execute_script(script)
윈도우 중에서 마지막에 열린 윈도우로 현재 윈도우 변경하기
def switch_to_last_opened_window():driver.switch_to.window(driver.window_handles[-1])
iframe 으로 현재 프레임 변경하기
def switch_to_iframe(iframe):WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.TAG_NAME, "iframe"))
driver.switch_to.frame(iframe)
WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.TAG_NAME, "iframe"))
의 코드가 필요한 이유는 iframe 이 나중에 로드가 되어 약간의 딜레이를 주지 않고 바로 find~ 등을 진행할 경우 때때로 실패하는 것을 확인할 수 있습니다. 그렇기에 넉넉히 10초간 iframe tag 가 나오기를 기다리는 코드를 작성한 것입니다.
def pick_numbers():
picks = set([])
while 6 != len(picks):
n = random.randint(LOTTO_MIN_NUM, LOTTO_MAX_NUM)
picks.add(n)
return picks
화면 캡처하기
def save_screenshot():
driver.save_screenshot(f'{datetime.now().strftime("%Y%m%d_%H%M%S")}.png')
이제 위 함수를 참고하여 코드를 작성해보겠습니다.
팝업 닫기
sleep(1)
close_windows_if_not_main_url('common.do?method=main')
sleep(1) 을 추가한 이유는 팝업이 여러개 나타날 경우 팝업이 제대로 안 닫히는 경우가 있습니다. 그러므로 1초 동안 팝업이 다 열리기를 기다리는 것 입니다.
복권 구매 버튼 클릭 시 발생되는 script 실행
execute_script('goLottoBuy(2);')
저는 개인적으로 가능하다면 script 을 실행하는 편입니다. 그 이유는 selenium 을 통해 find~ 보다 변경이 적기 때문입니다. 또한 element 가 화면에 보이지 않을 경우 find 나 click 을 하려하면 에러를 발생시키는데 script 실행은 그에 비해 유연하기 때문입니다. 물론 상황에 따라서 적합한게 다를 것 입니다.
복권 구매 팝업 윈도우로 현재 윈도우 이동
switch_to_last_opened_window()
복권 번호 클릭을 위해 현재 frame 이동
switch_to_iframe(driver.find_elements(By.TAG_NAME, 'iframe')[0])
복권 번호 6개 클릭 후 번호 선택 확인 버튼 클릭
for num in pick_numbers():
execute_script(f'$("#check645num{num}").prop("checked", true);')
click(driver.find_element(By.ID, 'btnSelectNum'))
각 숫자는 checkbox 의 형식으로 되어있습니다. id 의 규칙을 보면 check645num 뒤에 1~45가 붙어있는 것임을 알 수 있습니다. 그렇기에 랜덤으로 6개의 숫자를 단순히 check645num 뒤에 붙여 checked 속성을 true 로 부여하였습니다.
구매하기 버튼 클릭
click(driver.find_element(By.ID, 'btnBuy'))execute_script('closepopupLayerConfirm(true);')
구매하기 버튼을 클릭하면 한 번 더 묻는 컨펌 다이얼로그가 나옵니다. 여기서 저는 해당 확인 버튼을 클릭하기 보다 js script 을 실행시키도록 하였습니다.
위 코드까지 실행하면 아래와 같이 구매 완료 화면이 나옵니다.
구매내역 확인 캡처
save_screenshot()
driver.quit()
댓글
댓글 쓰기