dev_eun

[Python] 토익 티켓팅 매크로 제작기 ② with Selenium 본문

개발일지/토이프로젝트

[Python] 토익 티켓팅 매크로 제작기 ② with Selenium

_eun 2020. 5. 17. 23:10

토익 시험 접수 사이트의 url를 가져온다.

url = 'http://www.ybmnet.co.kr/common/login.asp?url=https%3A%2F%2Fappexam%2Eybmnet%2Eco%2Ekr%2Ftoeic%2Freceipt%2Freceipt%2Easp&what=appexam%2Eybmnet%2Eco%2Ekr'

이 주소는 로그인을 하면 바로 시험 접수 창으로 넘어가는 주소다. 접속하게 되면

이런 화면이 뜬다. 그리고 ctrl + shift + C 를 눌러보자.
여기서 id를 입력하는 곳을 클릭해보면 textfield의 name값이 보인다. password과 버튼도 똑같이 진행해 보면
id의 name은 uid, password의 name은 pwd, 버튼의 name은 image임을 알 수 있다.
여기에 로그인할 값들을 전송하고 버튼까지 클릭한다.

driver.find_element_by_name('uid').send_keys(settings.ID)
driver.find_element_by_name('pwd').send_keys(settings.PASSWORD)
driver.find_element_by_name('name').click()
driver.implicitly_wait(10)

implicitly_wait함수는 페이지가 모두 로딩이 될 때까지 암묵적으로 최대 10초까지 기다리라는 함수이다.
여기까지 성공하면 이런 창이 뜰 것이다.

다시 ctrl + shift + C 을 누르고 내가 접수하고 싶은 접수장을 클릭해보자.
나는 현 시점에서 제일 최근의 접수장을 선택할 것이다. 그 첫 번째 선택지의 id는 toeic_time405이다. 같은 방식으로 지역을 선택한다. 서울의 경우 id값이 toeic_area201이다.

driver.find_element_by_id("toeic_times405").click()
driver.implicitly_wait(10)
...
driver.find_element_by_id("toeic_area201").click()
time.sleep(0.2)

time.sleep함수는 토익 서버에 무리가 가지 않게 하려고 넣어놓았다.
그 때 당시에는 접수 가능한 접수장이 없었기 때문에 지역을 선택했을 때 접수장이 나오는지 나오지 않는지 판단을 해야 했다.
접수장이 없을 경우 이런식으로 나온다.

저 '접수가능한 고사장이 없습니다.'의 문구가 있는 테이블의 id는 r_map_toeic이다. 그리고 접수 가능한 접수장이 없으면 dl>dd의 class의 값으로 no_data가 생긴다.
이것은 beautifulSoup으로 찾을 것이다.

req = driver.page_source
soup = BeautifulSoup(req, 'html.parser')
regionlist = soup.find('dd', class_="no_data")

현재 접속해 있는 페이지의 html 코드를 가져와서 dd 태그의 class값이 no_data인 것을 찾는다.
이렇게 했는데 regionlist에 값이 들어 있다면 접수 가능한 고사장이 없는 것이고, 없다면 접수 가능하다는 것이다.
이를 판단하여 없을 경우에는 r_map_toeic>dl>dt의 값으로 맨 처음에 뜬느 고사장을 가지고 오면 된다.

if regionlist is None:
    reg = soup.select('#r_map_toeic > dl > dt')
    if reg is not None and str(reg) != '[]':
        ...

그리고 reg는 가끔 오류 때문인지 '[]'라고 나올 때가 있어 체크를 한 번 더 하였다.
저기까지 확인이 완료가 되면 이제 접수를 할 수 있다.
r_map_toeic>dl>dt 이 값들을 모두 가져온 후 제일 첫 번째 element를 클릭한다. 그리고 위와 같은 방법으로 'ARS 성적확인 동의'와 '다음 단계' 버튼의 id 값을 찾는다.

ele = driver.find_elements_by_xpath("//div[@id='r_map_toeic']/dl/dd")
ele[0].click()
driver.find_element_by_id('ars2').click()

그런데 다음 단계의 버튼에는 id 값이 없고 class 값만 있다. class는 다른 엘리먼트와 중복될 수 있다. 그래서 버튼의 값을 찾기 위해 find_element_by_xpath함수를 사용할 것이다. 버튼의 tag를 찾아서 마우스 우클릭을 해보면 'Copy Xpath'가 있다. 그 기능을 이용해서 xpath를 복사한다.

driver.find_element_by_xpath("//p[@class='btn_wrap']/a").click()
driver.implicitly_wait(10)

그러면 다음 페이지로 넘어간다.
모두 동의 버튼, 성별 체크의 id다 xpath를 찾아 위와 같은 방법으로 실행한다.

driver.find_element_by_id('agreeChkAll').click()
driver.find_element_by_xpath("//p[@class='phone_wrap']/input[@value='0']").click()

그리고 상품권을 충전했다면 보유잔액이 뜰 것이다. 결제 금액을 입력하는 텍스트필드의 id값은 usecash이다. 여기서 맨 처음 로그인할 때 처러 send_keys함수를 사용한다. 금액을 입력한 후 적용 버튼을 누른다.

driver.find_element_by_id('usecash').send_keys('44500')
driver.find_element_by_id('BlurUsecash').click()

다음 단계 버튼도 id가 없으므로 xpath로 대체한다. 버튼을 클릭한 후 결제하기 버튼을 누르면 결제를 하겠냐는 알림창이 뜬다. 여기서 알람창의 확인 버튼을 눌러야 한다.

driver.find_element_by_xpath('/html/body/div[2]/p[3]/a[2]').click()
driver.find_element_by_xpath('/html/body/div[2]/div[2]/div[2]/p[3]/a[2]').click()
driver.implicitly_wait(10)

driver.switch_to.alert.accept()

이 확인 버튼까지 누르고 나면 접수가 끝났다!

728x90