2021년 8월 17일 화요일

수강신청 매크로 (수강신청 실패해서 빡쳐서 만든 매크로)

 오늘 수강신청이었는데 서버가 터졌다.

장바구니에 안 담긴게 3과목이라 3개를 신청했어야 하는데 1개밖에 못 건졌다.

원래 저번주가 수강신청이었는데 한번 터져서 오늘로 미룬 거였음에도 서버가 또 터졌다.

빡쳐서 매크로를 만들어보았다.

사용 언어는 파이썬이고, 크롬드라이버 기반 셀레니움을 사용하였다.

수강신청은 이미 실패했으니 누가 취소할 경우를 상정해서 자동으로 신청하도록 해야 한다.

(물론 아무도 취소안하면 못 건진다.)

우선 매크로를 만들기 위해 수강신청 화면을 들여다보자.

수강신청을 위해서는 총 3가지 interaction이 일어나야 한다.

1. 과목 옆의 체크리스트 클릭 (신청할 과목 선택)

2. 보안문자 입력

3. 수강신청 버튼 클릭


문제는 2번이다. 사실 보안문자가 없었으면 굳이 만들어 쓰지 않아도 쉽게 대체할 수 있다.

따라서 이를 해결하기 위해선 저 보안문자를 읽어서 인식하고 이를 숫자로 나타내야 한다.

1, 3번은 셀레니움 사용법만 이해하고 있다면 어렵지 않게 할 수 있으므로 생략.


그렇다면 저 보안문자를 어떻게 인식할 수 있을까?

우선 셀레니움에서 해당 부분을 이미지 형태로 불러오면 다음과 같이 된다. 



위는 모두 45인 경우를 나타낸 것이다. 위치, 크기, 폰트, 굵기, 회전 정도 모두 달라서 이를 인식하게 하기가 좀 골치아팠다. 

분류 단계를 요약하면 다음과 같다:

1. 이미지를 불러와서 두 숫자로 분리

2. CNN에 집어넣기 좋은 형태로 이미지 resize

3. MNIST 기반으로 CNN 학습

4. 학습된 모델을 직접 라벨링한 400개 정도의 이미지를 바탕으로 전이학습

5. 1번에서 분리한 숫자를 집어넣어 분류


우선 1번이다. 이미지를 불러와서 두 숫자로 분리하는 과정이다. 사실 그냥 색이 다른 부분만 적당히 사각형으로 잘라서 padding을 넣고 resize하면 깔끔하겠지만 아까는 빨리 만드는게 더 중요해서 그냥 생각나는대로 잘랐다. 알고리즘을 요약하면, 왼쪽에서 오른쪽으로 훑으면서 왼쪽 숫자와 오른쪽 숫자의 중간 부분에서 자르고, 숫자 주변으로 3~4px 정도 테두리를 주어서 MNIST 데이터와 최대한 유사하게 만들도록 노력했다. 물론 숫자 크기랑 위치가 치우쳐진 경우 고쳐놓은 데이터가 이쁘게 생기지 않았다. 이런 경우에 분류 에러가 발생하긴 한다.

아무튼 그런 과정을 거치고 나서, CNN의 인풋으로 집어넣을 수 있도록 resize를 해주었다. 위의 데이터는 26*52px이기 때문에, MNIST의 CNN 인풋으로 사용하기 위해 28*28px로 resize해주어야 했다. 구글링해보니 적당한 라이브러리가 있길래 그냥 가져다 썼다. 이런 과정을 거치고 나면 적당히 이쁘게 바뀐다. (아래 그림)

이제 그냥 keras 공홈에서 찾아볼 수 있는 CNN training 예제를 그대로 가져와서 학습을 시켰다. 
Link - https://www.tensorflow.org/tutorials/keras/classification?hl=ko
(여기 위는 fashion mnist데이터인데, 그냥 데이터를 mnist로 바꿔주기만 하면 된다.)

추가적으로, 여기서는 CNN을 사용한게 아니라 flatten하고 dense로만 구성하였기 때문에 모델은 아래 링크에서 제공하는 모델을 사용하였다. (성능 차이가 나서 아래 걸로 했음)
Link - https://www.tensorflow.org/tutorials/images/cnn?hl=ko

솔직히 이 상태면 바로 적용 가능할 줄 알았는데 위에 보이는 4와 5는 전처리가 잘 된 상태고, 그렇지 않은 데이터들은 생각보다 분류가 잘 되지 않았다. 그래서 이미지를 좀 받아서 직접 손으로 라벨링을 하고 다시 학습을 시켜주었다.


전이학습 없이 그냥 돌렸을 때의 정확도는 45%정도였다. 숫자 두개를 정확히 인식해야 하니까 0.45*0.45 = 0.2025 약 20%정도가 된다. 수강신청 사이트는 5번을 연속으로 틀리면 자동으로 로그아웃되기 때문에 랜덤으로 5번 시도시 약 33% 확률로 로그아웃된다. 그런데 로그아웃되면 다시 들어오게하기가 좀 귀찮아져서 전이학습이 필수적이다. 전이학습을 잘 시키고 나면 정확도가 거의 95%이상은 된다. (이미지 전처리가 잘 된 경우) 그래서 5번 연속 틀리는 일은 거의 일어나지 않는다. 물론 이미지 전처리가 잘 안됐을 경우에는 에러가 발생해서 틀리기는 하지만, 그래도 사람이 하는 것보다는 훨씬 빨리 루프가 돌기 때문에 나중에 보완해도 될 것 같아서 내버려두었다.

한편, 셀레니움으로 해당 이미지를 불러오려고 했을때 처음에는 Xpath를 이용했는데, 이유는 정확히 모르겠지만 이렇게 하면 계속 불러오는 이미지가 바뀐다. 실제 보는 화면과 다르게 되어있는 것 같다. 아마도 변수값을 시간과 관계있게 설정해놓아서 링크를 타고 이미지를 다운받으면 이미지가 계속 바뀌는 것 같다. 그래서 이를 해결하기 위해서 화면 캡처를 떠서 해당 이미지 부분을 잘라내는 방식을 사용했다. 이 경우 문제없이 화면과 일치하는 숫자를 내뱉게 된다. 

돌려보니 잘 작동한다.

나머지는 뭐 셀레니움을 적당히만 잘 쓰면 쉽게 해결할 수 있는 문제이기 때문에 그냥 생략하겠다. 코드는 정리되면 깃헙으로 올리고, 링크 걸어놓을 예정이다.

나중에 시간이 된다면 exe파일로 만들어서 배포할 생각도 있긴 하다.

근데 할 게 많아서 모르겠다.... 무튼 5시간에 걸쳐 만든 매크로 탄생기 끝.

학교 규정 위반임을 확인하고 더 이상은 사용하지 않았다. 어차피 취소여석이 남지 않아서 이걸로 유의미한 결과를 얻지는 못했고, 넣으려던 과목들은 정원 외 신청으로 다 넣어서 결과론적으로는 의미없었지만..


댓글 1개: