• 수강신청 자동화 with Selenium

    2021. 2. 19.

    by. ugonfor

    서론

    얼마전에 수강신청을 하였습니다.

     

    그런데, 언제나 계획대로 되는 건 없죠..

    제 계획은 24~25로 학점 꽉꽉 채워서 듣는 거였는 데, 한 과목을 놓쳐버렸습니다...

     

     

    과목명이랑 교수님 지운건 우리과 전공이라서...

     

    그래서 계속 놓친 과목을 누르고 있다가, 지쳐서 잠시 생각해보니까 수강신청 이거 자동화가 가능할거 같다는 생각이 들었습니다.

     

    그래서 셀레니움으로 수강신청 자동화 스크립트를 만들었습니다! (전산처 ㅈㅅ;)

     

    근데, 나중에 확인해보니까 올해부터 수강신청 방법이 바뀌어서 수강매매 방지를 위해서 드랍을 하게 되면, 드랍하자마자 수강신청이 열리는 것이 아니라 따로 알림창이 생긴다고 합니다. 몇시 몇분에 그 과목 풀린다고.. 그러니까 하염없이 광클을 할 필요가 없는거죠..

     

    허허...

     

     

    그래서 어차피 수신도 끝났고, 필요도 없어지고 소용도 없는거 매크로 만드는 과정이 나름 재밌었기에, 그 과정을 공유하고자 합니다.


    수강신청 자동화 with Selenium

    환경 설정

    필요한 툴은 다음과 같습니다.

    tools :
    
    chromedriver
    tesseract-ocr
    python
    
    python package :
    
    selenium
    BeautifulSoup
    pytesseract
    Pillow
    openCV
    requests

     

    chromedriver

    selenium

    은 웹 동작시킬 때 필요하고,

     

    bs4는 스크래핑 하는 부분 있어서 필요했고,

     

    나머지부분은 중간에 매크로 방지를 위해서 특정 문자열 입력하라고 하는 부분

     

    이런거

     

    생기는 데, 이거 제대로 입력하는 거 자동화하기 위해 필요합니다.

     

    시나리오

    1. 수강신청 사이트에 접속

    2. 알림창 닫기

     

     

    3. 로그인

    4. 수강과목 검색

    5. 신청

    6. 마감 창 닫기

     

     

    7. 5.부터 다시 반복

    8. 만약 매크로 방지 창이 뜰 경우, 이미지 가져와서 OCR 후 입력해주기

    9. 마감 알림창 or 매크로 방지 창이 뜨지 않을 때까지 반복

    10. 성공!

     

    이런 시나리오로 구현을 하게 됩니다.

     

    구현

    기본 틀

    코드는 혹시라도 악용될까봐... 텍스트 말고 사진으로 첨부하고자 합니다.

     

    import한 모듈은 다음과 같습니다.

    사실, 셀레니움부분은 타 블로그에서 그냥 긁어왔는 데 스크립트 쓰다 보니까 맨 위에 selenium만 import했어도 잘 작동했을 거 같습니다.

     

     

     

    처음 사이트 접속은 아래 코드처럼 설정을 해줍니다.

    argument를 추가해주는 이유는 보통 user-agent가 일반 크롬이나 브라우저로 접속하면 아래와 같이 되는 데, 셀레니움이나 파이썬 모듈 등으로 하게 되면 이에 대한 정보가 남아있어서 user-agent를 설정해주었습니다.

     

     

    에러나는 경우들이 있어서 try/except로 처리를 해주었고, 에러가 발생할 경우에는 driver를 종료하고, 새로 크롬브라우저를 열게 했습니다.

     

     

    셀레니움을 이용하게 되면, 사람이 손으로 하는 것들을 모두 파이썬 스크립트로 할 수 있게 됩니다. 

     

    아래의 코드의 경우에는 element에서 xpath를 통해서 위치를 찾고 그 element에 대해서 click을 하는 것입니다.

    마우스 클릭하는 거죠.

    driver.find_element_by_xpath('/html/body/div[6]/div[2]/div/div/div/div/div/div/div/div[1]').click()
    
    

    xpath로 하게되면 사람이 보기는 어렵지만, 컴퓨터는 헷갈리지 않고 제대로 찾아갑니다.

    그래서 저만 사용할 거기에 그냥 이런식으로 했습니다.

     

    xpath의 경우 "ctrl + shift + c"를 눌러서 아래처럼 나타날 때,

     

     

    아래 사진처럼 Copy XPath를 하게 되면, XPath 정보를 얻을 수 있습니다.

     

     

    이런 식으로 하였고,

    driver.find_element_by_xpath("####").click()
    driver.find_element_by_xpath("####").send_keys("####")

    위와 같은 코드를 통해서 클릭, 키보드 채우기 등을 수행하였다.

     

    기본적인 틀은 지금까지 설명한 바와 같다.

    셀레니움을 이용해서 화면에 보이는 element들을 조작하고, 이를 통해 수강신청을 하였다.

    위 방법을 이용하게 되면, 누구나 쉽게 수강신청 자동화 작업을 할 수 있다.

     

    다음은 특이사항으로 따로 신경써주어야 하는 부분에 대해서 서술할 것이다.

     

    iframe 다루기

    처음에 Element를 다루면서 계속해서 에러가 나길래, 왜 에러가 나는 지 확인을 해보았습니다.

    page source를 확인해 보았는 데, iframe으로 처리를 하고 있어서 ctrl+u로 source를 확인해보아도 내부 컨텐츠에 대한 element들이 표시가 되지 않았습니다.

     

    그래서 셀레니움을 이용해도, 제대로 동작을 하지 않았습니다.

     

     

    iframe id='Main'

     

    iframe이란, 페이지 안에 페이지를 삽입하는 것인 데, 굉장히 많은 사이트에서 위와 같은 방법을 이용해서 페이지를 구성하고 있습니다.

     

    셀레니움에서 이를 고려하는 방법은 아래처럼 다루는 frame을 변경하면 됩니다.

    위에서 iframe의 id가 'Main'이었는 데, 그래서 아래처럼 'switch_to_frame' 명령어를 통해 frame을 변경해 주면 제대로 동작하는 걸 확인할 수 있습니다.

     

     

     

    매크로 방지 통과

    자동화를 만들면서 가장 재미있었던 부분이 이부분입니다.

    매크로 방지를 통과해야 합니다.

     

    이제는 수강신청이 끝나버려서 그 화면을 보여줄 수가 없는 데, 

     

    발그림 ㅈㅅ

     

    위 사진 처럼, 사진 보여주고, 그에대해서 텍스트를 입력하게 되면 매크로 방지가 통과되는 것이었습니다.

     

    이거를 해결하지 못하면 자동화가 전혀 소용이 없어지게 됩니다.

    그래서 매크로방지를 적절히 우회할 수 있게 하고자 했습니다.

     

    먼저, 사진파일을 로컬로 가져와야 했습니다.

    pre-trained model을 돌리든 말든 하려면 일단 사진을 가져와야 가능한 것이기에 src에서 가져오려고 했습니다.

    그래서 element 태그를 확인해보았고, 사진파일의 src가 적혀있는 것을 확인할 수 있었습니다. (src에 접속하면 사진파일에 접근 가능함)

     

    그래서 BeautifulSoup을 이용해서 파싱하고, 파일을 가져오려고 했는 데, requests 모듈로 get 요청 보내니까, 코드가 200이 아니었습니다.

     

    그래서 확인을 해보니, 실제로 타 브라우저로 접속을 하니까 같은 주소임에도 접근이 불가능했습니다.

    nonce처럼 일회적으로 생성되는 사진파일이었습니다.

     

    그래서 이를 어떻게 접근 가능하게 할까 하고 생각해봤는 데, 아마 세션값을 유지해주면 가능할 거 같아서 쿠키설정을 해준 후, request를 보냈더니 정확하게 가능했습니다 :)

     

    그래서 사진파일을 로컬로 가져왔습니다.

     

    그 다음, OCR(광학문자인식) 기능을 제공하는 툴을 설치했습니다.

    설치한 것은 tesseract-ocr-w64-setup-v5.0.0-alpha.20201127 입니다.

    그리고 이는 import pytesseract 를 통해서 쉽게 사용 가능합니다. (물론 환경변수 설정해야 함.)

     

    사진파일을 바로 pytesseract를 이용해서 문자열로 변환 해봤는 데, 

    pytesseract.image_to_string(Image.open('img.gif'),lang='eng')
    

    제대로된 인식이 불가능하였습니다.

     

    그래서 인식률을 높이기 위해서 어떻게 해야할 지 고민했는 데, 일단 파일형식을 gif에서 png로 변환하고, 아래 사진처럼 무채색으로 변환을 하게 되니, 인식이 훨씬 잘 됬습니다. (회색 변환할 때, openCV사용)

     

     

     

    나머지는 셀레니움으로 다시 텍스트입력하고 확인을 누르게 하니 정상적으로 자동화가 되더군요 ㅎㅎ


    하여튼 위처럼 수강신청 자동화를 만들어 봤는 데, 열심히 클릭을 해주는 것만으로는 좋은 강의를 얻는 것이 불가능해 보이는 군요...

     

    나름 만드는 과정이 재밌었어서 작성해봤습니다.

     

    시간고려해서 정각에 누르게 만들면 잡을 수도 있을 거 같긴하네요 ㅎㅎ

     

    전산처에서 매크로 방지할려고 꽤 노력한 거 같은 데.. 음... 약간 클릭 매크로? 정도만 불가능하게 만든거 같아요.

    그냥 타대학처럼 선착순말고 점수추첨제? 그런거로 하는 게 나은 거 같기도하고....

     

    참고로, 저는 이거 만들었지만 강의 줍지는 못했습니다 ㅋㅋㅠ

    댓글