import sys import asyncio from PyQt5.QtWidgets import (QApplication, QWidget, QVBoxLayout, QLabel, QLineEdit, QPushButton, QComboBox, QTextEdit, QFileDialog, QHBoxLayout) from PyQt5.QtCore import Qt from playwright.async_api import async_playwright from PyQt5.QtGui import QClipboard class PlaywrightTester(QWidget): def __init__(self): super().__init__() # GUI 레이아웃 설정 self.initUI() self.browser = None self.page = None self.elements = [] # 여러 요소를 찾을 때 저장하는 리스트 self.current_element_index = 0 # 현재 확인 중인 요소 인덱스 self.playwright = None self.log_file_path = None self.clipboard = QApplication.clipboard() def initUI(self): layout = QVBoxLayout() # 테스트할 URL 입력 필드 self.url_input = QLineEdit(self) self.url_input.setPlaceholderText("Enter URL to test") self.url_input.setText("https://percenty.co.kr") layout.addWidget(self.url_input) # 선택자 타입 설명 라벨 self.selector_type_label = QLabel("Selector Type (CSS, XPath, Name):") layout.addWidget(self.selector_type_label) # 선택자 타입 콤보박스 (CSS, XPath, Name) self.selector_type_combobox = QComboBox() self.selector_type_combobox.addItems(["CSS", "XPath", "Name"]) self.selector_type_combobox.currentIndexChanged.connect(self.update_selector_input) layout.addWidget(self.selector_type_combobox) # 선택자 입력 필드 self.selector_input = QLineEdit(self) self.selector_input.setPlaceholderText("Enter selector here (CSS, XPath, Name)") layout.addWidget(self.selector_input) # Playwright 실행 버튼 self.playwright_button = QPushButton("Start Playwright", self) self.playwright_button.clicked.connect(self.start_playwright) layout.addWidget(self.playwright_button) # 요소 찾기 버튼 self.find_button = QPushButton("Find Element", self) self.find_button.clicked.connect(self.find_element) layout.addWidget(self.find_button) # 요소 클릭 버튼 self.click_button = QPushButton("Click Element", self) self.click_button.clicked.connect(self.click_element) layout.addWidget(self.click_button) # 다음 요소 확인 버튼 (여러 요소가 있을 때) self.next_element_button = QPushButton("Next Element", self) self.next_element_button.clicked.connect(self.show_next_element) layout.addWidget(self.next_element_button) # 선택자 복사 버튼 self.copy_selector_button = QPushButton("Copy Selector", self) self.copy_selector_button.clicked.connect(self.copy_selector) layout.addWidget(self.copy_selector_button) # 로그 창 (출력 결과 표시) self.log_output = QTextEdit(self) self.log_output.setReadOnly(True) layout.addWidget(self.log_output) # 메인 레이아웃 설정 self.setLayout(layout) self.setWindowTitle('Playwright Element Tester') self.setGeometry(300, 300, 400, 400) def log_message(self, message): """로그 출력 및 저장""" self.log_output.append(message) def update_selector_input(self): """선택자 타입에 따라 입력 필드를 업데이트""" selector_type = self.selector_type_combobox.currentText() if selector_type == "Name": self.selector_input.setPlaceholderText("Enter text to find elements by Name") else: self.selector_input.setPlaceholderText(f"Enter {selector_type} selector here") async def async_playwright_setup(self, url): """Playwright 비동기 실행 및 페이지 설정""" self.playwright = await async_playwright().start() self.browser = await self.playwright.chromium.launch(headless=False) # 페이지 생성 시 viewport 설정 self.page = await self.browser.new_page(viewport={"width": 1920, "height": 1080}) await self.page.goto(url) def start_playwright(self): """Playwright 실행""" url = self.url_input.text() if not url: self.log_message("URL을 입력하세요.") return self.log_message(f"Playwright 실행 중... URL: {url}") loop = asyncio.get_event_loop() loop.run_until_complete(self.async_playwright_setup(url)) self.log_message("Playwright 실행 완료. 페이지 로드됨.") async def find_element_async(self): """요소 찾기 비동기 작업""" selector_type = self.selector_type_combobox.currentText() selector = self.selector_input.text() try: self.elements = [] # 요소 리스트 초기화 if selector_type == "CSS": self.elements = await self.page.query_selector_all(selector) elif selector_type == "XPath": self.elements = await self.page.query_selector_all(selector) elif selector_type == "Name": # 이름을 기준으로 요소 찾기 self.elements = await self.page.query_selector_all(f'[name="{selector}"]') if self.elements: self.current_element_index = 0 self.log_message(f"요소 찾기 성공. 총 {len(self.elements)}개의 요소 발견.") await self.show_current_element_info() else: self.log_message(f"요소를 찾을 수 없음: {selector}") except Exception as e: self.log_message(f"오류 발생: {e}", exc_info=True) def find_element(self): """요소 찾기 동작""" self.log_message("요소 찾기 시작...") loop = asyncio.get_event_loop() loop.run_until_complete(self.find_element_async()) async def show_current_element_info(self): """현재 선택된 요소의 정보를 표시""" if not self.elements: self.log_message("요소가 없습니다.") return current_element = self.elements[self.current_element_index] selector_type = self.selector_type_combobox.currentText() # 요소 정보 출력 if selector_type == "CSS": element_info = await current_element.evaluate("e => e.outerHTML") self.log_message(f"요소 {self.current_element_index + 1}/{len(self.elements)} 정보: {element_info}") elif selector_type == "XPath": element_info = await current_element.evaluate("e => e.outerHTML") self.log_message(f"요소 {self.current_element_index + 1}/{len(self.elements)} 정보: {element_info}") elif selector_type == "Name": element_info = await current_element.evaluate("e => e.outerHTML") self.log_message(f"요소 {self.current_element_index + 1}/{len(self.elements)} 정보: {element_info}") def show_next_element(self): """다음 요소 확인""" if not self.elements: self.log_message("찾은 요소가 없습니다.") return self.current_element_index = (self.current_element_index + 1) % len(self.elements) loop = asyncio.get_event_loop() loop.run_until_complete(self.show_current_element_info()) async def click_element_async(self): """요소 클릭 비동기 작업""" if not self.elements: self.log_message("요소가 없어서 클릭할 수 없습니다.") return try: current_element = self.elements[self.current_element_index] await current_element.click() self.log_message(f"요소 클릭 성공: {self.current_element_index + 1}/{len(self.elements)}") except Exception as e: self.log_message(f"클릭 오류 발생: {e}", exc_info=True) def click_element(self): """요소 클릭 동작""" self.log_message("요소 클릭 시작...") loop = asyncio.get_event_loop() loop.run_until_complete(self.click_element_async()) def copy_selector(self): """현재 선택한 요소의 선택자를 클립보드로 복사""" if not self.elements: self.log_message("복사할 요소가 없습니다.") return selector = self.selector_input.text() self.clipboard.setText(selector) self.log_message(f"선택자 복사 완료: {selector}") if __name__ == '__main__': app = QApplication(sys.argv) ex = PlaywrightTester() ex.show() sys.exit(app.exec_())