파이썬이 제일 쉬워

[Python/Selenium] ClassCard 리벤지, 테스트/매칭게임 자동화 본문

Python

[Python/Selenium] ClassCard 리벤지, 테스트/매칭게임 자동화

HighBright 2024. 6. 18. 00:50

ClassCard 매칭게임, 테스트 자동화 #1

 

안녕하세요.. 자.. 오늘은 얘전에 했었던 ClassCard 자동화를 다시 해보려고 합니다.

이게 업데이트가 좀 되가지고.. 많이 바뀌었더라고요?

근데, 매칭게임은 사실 고칠게 별로 없었구요 전에 코드로도 어느정도는 되더라고요.

아.. 근데 이제 문제가 좀 생겼슴다. 실제로 사용하는 세트가 출판사에서 제공하는 세트일 경우에,

듣기 파일 이름이 md5가 아니라 그냥 단어장-일차-번호 이런 순이라 이걸 알아낼 수 가 없어요...

그래서 영어 듣기가 나오면 직접해야합니다. 半자동으로 만족해야 할듯요...

 

2022.03.13 - [Python] - [Python] Selenium 실습, ClassCard 매칭 게임 자동화하기 #1 [Outdated]

 

[Python] Selenium 실습, ClassCard 매칭 게임 자동화하기 #1 [Outdated]

Selenium 실습, ClassCard 매칭 게임 자동화하기 #1  본 방법은 ClassCard 개편으로 인하여 더이상 사용하실 수 없습니다.양해바랍니다. 다시 제작중 곧 새로 찾아뵐게연!공교육, 사교육에서 가리지 않

highbright.tistory.com

 

매칭게임에 대한 설명 및 코드 설명은 이거 보고 오시면 될 듯합니다.

 

매칭 게임에서 수정한 거는 몇개 없습니다.

그냥 dict 만드는 것만 살짝 바꾸고, 몇가지 대응 추가하고...

그리고 사이트 자체에서 selenium으로 접속하는 걸 막아놓으려고 했더라고요.

그래서 그거 우회하는 코드정도만 추가해줬습니다.

 

그리고 GUI 추가!

 

아래는 매칭게임만 가능한 전체코드입니다.

더보기
import tkinter as tk
from tkinter import filedialog
import time
import selenium.common.exceptions
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.chrome.options import Options
import time
import hashlib
import threading
class App:
    def __init__(self, root):
        self.start_thread = threading.Thread(target=self.start)
        self.process_thread = threading.Thread(target=self.process)
       
        self.root = root
        self.root.title("ClassCard Auto")
        self.file_loc = tk.Label(root, text="단어장")
        self.file_loc.grid(row=0, column=0, padx=10, pady=10)
        self.file_entry = tk.Entry(root, width=50)
        self.file_entry.grid(row=0, column=1)
        self.file_button = tk.Button(root, text="찾기", command=self.file_select)
        self.file_button.grid(row=0, column=2, padx=10, pady=10)
       
        self.link_label = tk.Label(root, text="주소")
        self.link_label.grid(row=1, column=0, padx=10, pady=10)
        self.link_entry = tk.Entry(root, width=50)
        self.link_entry.grid(row=1, column=1, padx=10, pady=10, columnspan=2)
 
        self.id_label = tk.Label(root, text="ID")
        self.id_label.grid(row=2, column=0, padx=10, pady=10)
        self.id_entry = tk.Entry(root, width=50)
        self.id_entry.grid(row=2, column=1, padx=10, pady=10, columnspan=2)
 
        self.pw_label = tk.Label(root, text="PW")
        self.pw_label.grid(row=3, column=0, padx=10, pady=10)
        self.pw_entry = tk.Entry(root, width=50)
        self.pw_entry.grid(row=3, column=1, padx=10, pady=10, columnspan=2)
        self.match = tk.IntVar()
        self.is_matching = tk.Checkbutton(root, text="매칭게임", variable=self.match)
        self.is_matching.grid(row=4, column=0, padx=10, pady=10)
 
        self.start_button = tk.Button(root, text="시작", command=self.start_thread.start, width=50)
        self.start_button.grid(row=4, column=1, padx=10, pady=10, columnspan=2)
       
        self.log = tk.Text(root, height=10)
        self.log.bind("<Key>", lambda e: "break")
        self.log.grid(row=5, column=0, padx=10, pady=10, columnspan=3)
       
    def start(self):
        try:
            self.start_button.configure(state="disabled")
            self.log.insert(tk.END, "프로세스 시작...\n")
           
            self.engdict = self.make_answer("answer.txt")
            self.md5dict = {}
            for i in range(int(len(self.engdict)/2)):
                engword = list(self.engdict.keys())[i]
                md5word = self.md5_encode(engword)
                self.md5dict[md5word] = engword
            self.log.insert(tk.END, "단어 dict 생성 완료.\n")
           
           
            service = Service(ChromeDriverManager().install())
            options = Options()
            options.add_argument('--disable-blink-features=AutomationControlled')
            self.driver = webdriver.Chrome(service=service, options=options)
            login_url = 'https://www.classcard.net/Login'
            user_id = self.id_entry.get()
            user_pw = self.pw_entry.get()
            self.driver.get(login_url)
            id_input = self.driver.find_element(By.ID, 'login_id')
            pw_input = self.driver.find_element(By.ID, 'login_pwd')
            login_button = self.driver.find_element(By.XPATH, '//*[@id="loginForm"]/div[3]/button')
            id_input.send_keys(user_id)
            pw_input.send_keys(user_pw)
            login_button.click()
            time.sleep(1)
            self.log.insert(tk.END, "로그인 완료, 시작하시려면 '진행' 버튼을 눌러주세요.\n")
            self.start_button.configure(state="active")
            self.start_button.configure(text="진행")
            self.start_button.configure(command=self.process_thread.start)
           
        except Exception as e:
            self.log.insert(tk.END, "오류 발생 : " + str(e) + "\n")
            self.start_button.configure(state="active")
            self.start_button.configure(text="시작")
            self.start_button.configure(command=self.start_thread.start)
       
    def stop(self):
        exit()    
   
    def file_select(self):
        folder_path = filedialog.askopenfilename()
        if folder_path:
            self.file_entry.insert(0, folder_path)
   
    def process(self):
        if self.match.get() == 1:
            self.matching()
        else:
            self.testing()
   
    def md5_encode(self, word):
        md5_hash = hashlib.md5()
        word_b = word.encode('utf-8')
        md5_hash.update(word_b)
        result = md5_hash.hexdigest()
        return result
       
    def invert_dic(self, original_dict):
        inverted_dict = {v: k for k, v in original_dict.items()}
        return inverted_dict
    def make_answer(self, file_path):
        eng_dic = {}
        with open(file_path, 'r', encoding='utf-8') as f:
            lines = f.readlines()
            for line in lines:
                line = line.strip()
                if line:
                    key, value = line.split('\t')
                    eng_dic[key] = value
                   
        han_dic = self.invert_dic(eng_dic)
        return dict(eng_dic, **han_dic)
   
   
    def matching(self):
        self.driver.get(self.link_entry.get())
        time.sleep(1)
        start_button = self.driver.find_element(By.XPATH, '//*[@id="wrapper-learn"]/div[2]/div/div[3]/div/div[2]')
        start_button.click()
        while True:
            try:
                lc1 = self.driver.find_element(By.XPATH, value='//*[@id="left_card_0"]/div/div[1]/div/div')
                lc2 = self.driver.find_element(By.XPATH, value='//*[@id="left_card_1"]/div/div[1]/div/div')
                lc3 = self.driver.find_element(By.XPATH, value='//*[@id="left_card_2"]/div/div[1]/div/div')
                lc4 = self.driver.find_element(By.XPATH, value='//*[@id="left_card_3"]/div/div[1]/div/div')
                rc1 = self.driver.find_element(By.XPATH, value='//*[@id="right_card_0"]/div/div/div/div')
                rc2 = self.driver.find_element(By.XPATH, value='//*[@id="right_card_1"]/div/div/div/div')
                rc3 = self.driver.find_element(By.XPATH, value='//*[@id="right_card_2"]/div/div/div/div')
                rc4 = self.driver.find_element(By.XPATH, value='//*[@id="right_card_3"]/div/div/div/div')
                a = 0
                for lc in [lc1, lc2, lc3, lc4]:
                    lct = lc.text
                    if lct == "":
                        lc = self.driver.find_element(By.XPATH, value=f'//*[@id="left_card_{str(a)}"]/div/div[1]/div/a/i')
                        temp1 = lc.get_attribute("data-src")
                        temp2 = temp1.split("/")[-1].rstrip(".mp3")
                        lct = self.md5dict.get(temp2)
                    for rc in [rc1, rc2, rc3, rc4]:
                        if rc.text in self.engdict[lct]:
                            lc.click()
                            rc.click()
                            time.sleep(1.5)
                    a = a+1
           
            except KeyError:
                self.log.insert(tk.END, "오류: 사전에 없는 단어\n")
            except selenium.common.exceptions.NoSuchElementException:
                self.log.insert(tk.END, "오류: 해당하는 오브젝트를 찾을 수 없음\n")
            except selenium.common.exceptions.StaleElementReferenceException:
                #self.log.insert(tk.END, "오류: 요소가 존재하지 않음\n")
                pass
            except selenium.common.exceptions.ElementNotInteractableException:
                self.log.insert(tk.END, "오류: 요소에 접근 할 수 없음\n")
            except selenium.common.exceptions.ElementClickInterceptedException:
                self.log.insert(tk.END, "오류: 요소에 접근 할 수 없음\n")
            except selenium.common.exceptions.NoSuchWindowException:
                self.log.insert(tk.END, "오류: 창이 닫혔거나 접근할 수 없음")
            except Exception as e:
                self.log.insert(tk.END, "오류: " + str(e) + "\n")
               
    def testing(self):
        pass
   
if __name__ == "__main__":
    root = tk.Tk()
    app = App(root)
    root.mainloop()

자... 이제 새로 추가된 테스트를 자동화 해봅시다.

진짜 이거 땜에 고생 개많이 했네요...

일단 왜인지 모르겠는데 selneium으로 text 가져오는 게 안되더라고요

일부러 막아놓은건지 뭔지는 모르겠는데;;

그래서 그냥 html 태그 자체를 가져와서 거기에 text를 추출하는 방식으로 해야했습니다.

코드 짜는건 얼마 안걸렸는데 이거 하는데 몇시간 박은 듯...

무튼 가봅시다.

 

일단 먼저 기본 세팅을 해줄건데, selenium이 조금 바뀌어서 이제 직접 chromedriver를

다운로드 할 필요가 없더라고요 

 
import selenium.common.exceptions
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.chrome.options import Options
 
service = Service(ChromeDriverManager().install())
options = Options()
options.add_argument('--disable-blink-features=AutomationControlled')
driver = webdriver.Chrome(service=service, options=options)

 

options.add_argument('--disable-blink-feautres=AutomationControlled')

얘 추가해주는 이유는 설정안하고 그냥 접속하게 되면 사이트에서 차단을 해버려서 꼭 해줘야합니당.

 

자, 이제 기초 세팅은 끝났고,먼저 dict를 좀 만들어야합니다.

전에는 뭐 엑셀에다가 하고 그랬는데 좀 더 범용성있게 그냥 텍스트 파일에서 긁어올 수 있게 해봤습니다.

그냥 사이트에서 바로 긁어오면 되지 않나 싶긴한데,

그 출판사에서 제공하는 세트는 그걸 제공을 안합니다...

그래서 걍 인쇄하는 거에서 긁어와서 텍스트 파일에 저장하고,

그걸 다시 dict로 만드는게 나을 것 같아서 일케 만들었습니다.

복사에서 메모장에 붙여넣기 ㄱㄱ 클래스카드 PRO~~ 이거 없애줘야함

 

텍스트 파일에 집어 넣었으면 요거를 다시 dict로 만들어 줄 코드를 짜봅시다.

영어/한글 둘 다 필요하니까 영어로 만들고 key, value를 반전시켜서 한글로도 만들껍니다.

텍스트 파일을 보면 "영단어(tab)뜻" 이런 식으로 되있습니다.

그래서 줄마다 읽어와서 tab단위로 분리시키고 각각 key와 value에 저장해줍시다.

def invert_dic(original_dict):
    inverted_dict = {v: k for k, v in original_dict.items()} # key, value 반전 저장
    return inverted_dict
 
def make_answer(file_path): 
        eng_dic = {}
        with open(file_path, 'r', encoding='utf-8') as f:
            lines = f.readlines()
            for line in lines:
                line = line.strip()
                if line:
                    key, value = line.split('\t') # tab 단위로 분리
                    eng_dic[key] = value # 사전에 저장
                   
        han_dic = invert_dic(eng_dic) # 반전시켜서 한글 사전 만들기
        return dict(eng_dic, **han_dic) # 둘이 합쳐준거 return
 
dic = make_answer("dict.txt")

 

자 이제 사전은 만들었으니, 다음 단계로 테스트 내부의 html 코드를 좀 살펴보면

 

이런 식으로 규칙적인 형태의 배치를 확인할 수 있습니다.

얘내의 XPATH는 '//*[@id="test_form]/div[문제번호]/... 이런 식입니다.

 

우리가 구해야하는 애들입니다.

쟤내들을 찾아서 text만 추출하면 되죠.

문제 번호는 여기서 파싱해옵시다.

파싱하기전에 아까 말했듯 html 자체를 가져와야 하기 때문에,

html에서 text만 뽑아내는 함수를 하나 만들어 줄겁니다.

def take_text(html):
        match = re.search(r'>(.*?)<', html) # >과 < 사이에 있는 텍스트 추출 <div>hello<div>면 hello 추출
        return match.group(1)
que_num = driver.find_element(By.CLASS_NAME, 'current-quest-num').text # 문제 번호 가져요기
question = take_text(driver.find_element(By.XPATH, f'//[@id="testForm"]/div[{que_num}]/div/div[1]/div[2]/div[1]').get_attribute('outerHTML')) # 문제 단어 가져오기

 

que_num은 문제 번호를 파싱해온거고,

왠지 모르겠는데 저 문제번호는 걍 .text로 파싱이 돼서 저렇게 짰습니다.

question은 그 문제 번호를 이용해서 문제 단어를 가져오는 코드입니다.

이제 이 문제를 이용해서 dict에서 답을 구한 후에, 답이 카드에 써있는 것과 같으면 그 카드를 클릭하도록 짜줍시다.

answer = dic[question]
for i in range(6): # 카드 수만큼 반복
    card = driver.find_element(By.XPATH, f'//*[@id="testForm"]/div[{que_num}]/div/div[2]/div/div[1]/div[{i+1}]/label/div/div') # 카드 요소 가져오기
    if take_text(card.get_attribute('outerHTML')) == answer:
         while que_num == driver.find_element(By.CLASS_NAME, 'current-quest-num').text: # 카드에 써진게 답과 같으면
              card.click() # 클릭
              time.sleep(0.1)

 

끝입니다. 요고를 그냥 반복문 돌려주면 되요.

몇가지 예외처리 해주고, 편의성 기능 몇개 넣어주면 더 좋고용.

하지만.. 역시 gui 없음 심심하죠? 바로 만들어줍니다.

import tkinter as tk
from tkinter import filedialog
import time
import selenium.common.exceptions
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.chrome.options import Options
import time
import hashlib
import threading
import re

class App:
    def __init__(self, root):
        self.test = 0
        self.stop_check = threading.Event()
        self.start_thread = threading.Thread(target=self.start, daemon=True)
        self.process_thread = threading.Thread(target=self.process, daemon=True)
       
        self.root = root
        self.root.title("Grand-ClassCard-Auto")

        self.file_loc = tk.Label(root, text="단어장")
        self.file_loc.grid(row=0, column=0, padx=10, pady=10)
        self.file_entry = tk.Entry(root, width=50)
        self.file_entry.grid(row=0, column=1)
        self.file_button = tk.Button(root, text="찾기", command=self.file_select)
        self.file_button.grid(row=0, column=2, padx=10, pady=10)
       
        self.link_label = tk.Label(root, text="주소")
        self.link_label.grid(row=1, column=0, padx=10, pady=10)
        self.link_entry = tk.Entry(root, width=50)
        self.link_entry.grid(row=1, column=1, padx=10, pady=10, columnspan=2)

        self.id_label = tk.Label(root, text="ID")
        self.id_label.grid(row=2, column=0, padx=10, pady=10)
        self.id_entry = tk.Entry(root,, width=50)
        self.id_entry.grid(row=2, column=1, padx=10, pady=10, columnspan=2)

        self.pw_label = tk.Label(root, text="PW")
        self.pw_label.grid(row=3, column=0, padx=10, pady=10)
        self.pw_entry = tk.Entry(root, width=50)
        self.pw_entry.grid(row=3, column=1, padx=10, pady=10, columnspan=2)

        self.match = tk.IntVar()
        self.is_matching = tk.Checkbutton(root, text="매칭게임", variable=self.match)
        self.is_matching.grid(row=4, column=0, padx=10, pady=10)
       
        self.start_button = tk.Button(root, text="시작", command=self.start_thread.start, width=50)
        self.start_button.grid(row=4, column=1, padx=10, pady=10, columnspan=2)
       
        self.log = tk.Text(root, height=10)
        self.log.bind("<Key>", lambda e: "break")
        self.log.grid(row=5, column=0, padx=10, pady=10, columnspan=3)
       



    def start(self):
        try:
            self.start_button.configure(state="disabled")
            self.log.insert(tk.END, "프로세스 시작...\n")
           
            self.dict = self.make_answer("answer.txt")
            self.md5dict = {}

            for i in range(int(len(self.dict)/2)):
                engword = list(self.dict.keys())[i]
                md5word = self.md5_encode(engword)
                self.md5dict[md5word] = engword
            self.log.insert(tk.END, "단어 dict 생성 완료.\n")
           
           
            service = Service(ChromeDriverManager().install())
            options = Options()
            options.add_argument('--disable-blink-features=AutomationControlled')
            self.driver = webdriver.Chrome(service=service, options=options)
            login_url = 'https://www.classcard.net/Login'
            user_id = self.id_entry.get()
            user_pw = self.pw_entry.get()
            self.driver.get(login_url)
            id_input = self.driver.find_element(By.ID, 'login_id')
            pw_input = self.driver.find_element(By.ID, 'login_pwd')
            login_button = self.driver.find_element(By.XPATH, '//*[@id="loginForm"]/div[3]/button')
            id_input.send_keys(user_id)
            pw_input.send_keys(user_pw)
            login_button.click()
            time.sleep(1)
            self.driver.get(self.link_entry.get())
            time.sleep(1)
            self.log.insert(tk.END, "로그인 완료, 시작하시려면 '진행' 버튼을 눌러주세요.\n")
            self.log.insert(tk.END, "매칭게임인 경우 그냥 누르시고\n테스트인 경우 테스트 창에 접속하신후 눌러주세요.\n")
           
            self.start_button.configure(state="active")
            self.start_button.configure(text="진행")
            self.start_button.configure(command=self.process_thread.start)
           
        except Exception as e:
            self.log.insert(tk.END, "오류 발생 : " + str(e) + "\n")
            self.start_button.configure(state="active")
            self.start_button.configure(text="시작")
            self.start_button.configure(command=self.start_thread.start)

    def file_select(self):
        folder_path = filedialog.askopenfilename()
        if folder_path:
            self.file_entry.insert(0, folder_path)
   
    def process(self):
        while not self.stop_check.is_set():
            if self.match.get() == 1:
                self.matching()
            else:
                self.testing()
               
    def md5_encode(self, word):
        md5_hash = hashlib.md5()
        word_b = word.encode('utf-8')
        md5_hash.update(word_b)
        result = md5_hash.hexdigest()
        return result
       
    def invert_dic(self, original_dict):
        inverted_dict = {v: k for k, v in original_dict.items()}
        return inverted_dict

    def make_answer(self, file_path):
        eng_dic = {}
        with open(file_path, 'r', encoding='utf-8') as f:
            lines = f.readlines()
            for line in lines:
                line = line.strip()
                if line:
                    key, value = line.split('\t')
                    eng_dic[key] = value
                   
        han_dic = self.invert_dic(eng_dic)
        return dict(eng_dic, **han_dic)
   
   
    def matching(self):
        start_button = self.driver.find_element(By.XPATH, '//*[@id="wrapper-learn"]/div[2]/div/div[3]/div/div[2]')
        start_button.click()
        while True:
            try:
                lc1 = self.driver.find_element(By.XPATH, value='//*[@id="left_card_0"]/div/div[1]/div/div')
                lc2 = self.driver.find_element(By.XPATH, value='//*[@id="left_card_1"]/div/div[1]/div/div')
                lc3 = self.driver.find_element(By.XPATH, value='//*[@id="left_card_2"]/div/div[1]/div/div')
                lc4 = self.driver.find_element(By.XPATH, value='//*[@id="left_card_3"]/div/div[1]/div/div')

                rc1 = self.driver.find_element(By.XPATH, value='//*[@id="right_card_0"]/div/div/div/div')
                rc2 = self.driver.find_element(By.XPATH, value='//*[@id="right_card_1"]/div/div/div/div')
                rc3 = self.driver.find_element(By.XPATH, value='//*[@id="right_card_2"]/div/div/div/div')
                rc4 = self.driver.find_element(By.XPATH, value='//*[@id="right_card_3"]/div/div/div/div')

                a = 0
                for lc in [lc1, lc2, lc3, lc4]:
                    lct = lc.text
                    if lct == "":
                        lc = self.driver.find_element(By.XPATH, value=f'//*[@id="left_card_{str(a)}"]/div/div[1]/div/a/i')
                        temp1 = lc.get_attribute("data-src")
                        temp2 = temp1.split("/")[-1].rstrip(".mp3")
                        lct = self.md5dict.get(temp2)

                    for rc in [rc1, rc2, rc3, rc4]:
                        if rc.text in self.engdict[lct]:
                            lc.click()
                            rc.click()
                            time.sleep(1.5)
                    a = a+1
           
            except KeyError:
                self.log.insert(tk.END, "오류: 사전에 없는 단어\n")
            except selenium.common.exceptions.NoSuchElementException:
                self.log.insert(tk.END, "오류: 해당하는 오브젝트를 찾을 수 없음\n")
            except selenium.common.exceptions.StaleElementReferenceException:
                #self.log.insert(tk.END, "오류: 요소가 존재하지 않음\n")
                pass
            except selenium.common.exceptions.ElementNotInteractableException:
                self.log.insert(tk.END, "오류: 요소에 접근 할 수 없음\n")
            except selenium.common.exceptions.ElementClickInterceptedException:
                self.log.insert(tk.END, "오류: 요소에 접근 할 수 없음\n")
            except selenium.common.exceptions.NoSuchWindowException:
                self.log.insert(tk.END, "오류: 창이 닫혔거나 접근할 수 없음\n")
                break
            except Exception as e:
                self.log.insert(tk.END, "오류: " + type(e).__name__ + "\n")
               
   
    def take_text(self, html):
        match = re.search(r'>(.*?)<', html)
        return match.group(1)

    def testing(self):
        while True:
            try:
                que_num = self.driver.find_element(By.CLASS_NAME, 'current-quest-num').text
                try:
                    checking = self.take_text(self.driver.find_element(By.XPATH, f'//*[@id="testForm"]/div[{que_num}]/div/div[1]/div/div[2]/div/a/div').get_attribute('outerHTML'))
                    if checking == "오디오 재생":
                        try:
                            audio_path = self.driver.find_element(By.XPATH, f'//*[@id="testForm"]/div[{que_num}]/div/div[1]/div/div[2]/div/a').get_attribute('data-src')
                            md5_question = audio_path.split("/")[-1].rstrip(".mp3")
                            question = self.md5dict.get(md5_question)
                            answer = self.dict[question]
                            for i in range(6):
                                card = self.driver.find_element(By.XPATH, f'//*[@id="testForm"]/div[{que_num}]/div/div[2]/div/div[1]/div[{i+1}]/label/div/div')
                                if self.take_text(card.get_attribute('outerHTML')) == answer:
                                    while que_num == self.driver.find_element(By.CLASS_NAME, 'current-quest-num').text:
                                        card.click()
                                        time.sleep(0.1)
                        except Exception as e:
                            self.log.insert(tk.END, "오류: " + type(e).__name__ + "\n")
                    else:
                        raise Exception("오류: 얘 정체가 뭔지 모르게서용\n")
                except:
                    question = self.take_text(self.driver.find_element(By.XPATH, f'//*[@id="testForm"]/div[{que_num}]/div/div[1]/div[2]/div[1]').get_attribute('outerHTML'))
                    answer = self.dict[question]
                    for i in range(6):
                        card = self.driver.find_element(By.XPATH, f'//*[@id="testForm"]/div[{que_num}]/div/div[2]/div/div[1]/div[{i+1}]/label/div/div')
                        if self.take_text(card.get_attribute('outerHTML')) == answer:
                            while que_num == self.driver.find_element(By.CLASS_NAME, 'current-quest-num').text:
                                card.click()
                                time.sleep(0.1)
                   
            except KeyError:
                self.log.insert(tk.END, "오류: 사전에 없는 단어\n")
            except selenium.common.exceptions.NoSuchElementException:
                self.log.insert(tk.END, "오류: 해당하는 오브젝트를 찾을 수 없음\n")
            except selenium.common.exceptions.StaleElementReferenceException:
                #self.log.insert(tk.END, "오류: 요소가 존재하지 않음\n")
                pass
            except selenium.common.exceptions.ElementNotInteractableException:
                self.log.insert(tk.END, "오류: 요소에 접근 할 수 없음\n")
            except selenium.common.exceptions.ElementClickInterceptedException:
                self.log.insert(tk.END, "오류: 요소에 접근 할 수 없음\n")
            except selenium.common.exceptions.NoSuchWindowException:
                self.log.insert(tk.END, "오류: 창이 닫혔거나 접근할 수 없음\n")
                break
            except Exception as e:
                self.log.insert(tk.END, "오류: " + type(e).__name__ + "\n")
               
               
if __name__ == "__main__":
    root = tk.Tk()
    app = App(root)
    root.mainloop()

 

아래는 작동 영상입니다.

(동영상)

 

 

잘되죠? 담에 봅시다!!

Comments