import sys import asyncio from PySide6.QtWidgets import (QApplication, QWidget, QVBoxLayout, QPushButton, QLineEdit, QTextEdit, QLabel) from PySide6.QtCore import Qt, QEvent from PySide6.QtGui import QTextCursor from playwright.async_api import async_playwright import qasync class WebAutomationApp(QWidget): def __init__(self): super().__init__() self.browser = None # 브라우저 객체를 저장할 변수 self.page = None # 페이지 객체를 저장할 변수 self.playwright_context = None # Playwright 컨텍스트 유지 self.initUI() def initUI(self): self.setWindowTitle('Web Automation with Playwright') # 레이아웃 설정 layout = QVBoxLayout() # 입력창 self.url_input = QLineEdit(self) self.url_input.setPlaceholderText("URL을 입력하세요 (예: https://www.naver.com)") layout.addWidget(QLabel("URL 입력:")) layout.addWidget(self.url_input) # 로그 출력 창 self.log_output = QTextEdit(self) self.log_output.setReadOnly(True) layout.addWidget(QLabel("로그 출력:")) layout.addWidget(self.log_output) # 네이버 연결 버튼 self.start_button = QPushButton("네이버 열기", self) self.start_button.clicked.connect(self.on_start_button_click) layout.addWidget(self.start_button) # 브라우저 닫기 버튼 self.close_browser_button = QPushButton("브라우저 닫기", self) self.close_browser_button.clicked.connect(self.on_close_browser_click) layout.addWidget(self.close_browser_button) # 종료 버튼 self.exit_button = QPushButton("종료", self) self.exit_button.clicked.connect(self.close_app) layout.addWidget(self.exit_button) self.setLayout(layout) async def open_naver(self, url): # Playwright를 이용해 네이버 웹페이지 열기 self.playwright_context = await async_playwright().start() self.log_message("Playwright 시작 중...") self.browser = await self.playwright_context.chromium.launch(headless=False) self.page = await self.browser.new_page() await self.page.goto(url) self.log_message(f"{url} 로 이동 중...") # 브라우저가 닫힐 때 감지 self.browser.on("disconnected", lambda: asyncio.ensure_future(self.close_app())) def log_message(self, message): self.log_output.append(message) self.log_output.moveCursor(QTextCursor.End) def on_start_button_click(self): url = self.url_input.text() if url == "": self.log_message("URL을 입력하세요.") return # 비동기 작업 시작 self.log_message(f"{url} 연결 시도 중...") asyncio.ensure_future(self.start_playwright_task(url)) async def start_playwright_task(self, url): try: await self.open_naver(url) except Exception as e: self.log_message(f"오류 발생: {e}") async def close_browser(self): if self.browser: await self.browser.close() await self.playwright_context.stop() self.log_message("브라우저 닫힘") self.browser = None else: self.log_message("열려 있는 브라우저가 없습니다.") def on_close_browser_click(self): asyncio.ensure_future(self.close_browser()) def close_app(self): self.log_message("프로그램 종료 중...") asyncio.ensure_future(self.close_browser()) # 프로그램 종료 전 브라우저 닫기 QApplication.instance().quit() # 애플리케이션 종료 def closeEvent(self, event): """GUI 창이 닫힐 때 호출되는 함수""" self.log_message("GUI 창이 닫히고 있습니다...") asyncio.ensure_future(self.close_browser()) # GUI 종료 시 브라우저 닫기 QApplication.instance().quit() # 이벤트 루프 종료 async def main(): app = QApplication(sys.argv) loop = qasync.QEventLoop(app) # qasync를 이용한 이벤트 루프 통합 asyncio.set_event_loop(loop) # asyncio 이벤트 루프 설정 main_window = WebAutomationApp() main_window.show() with loop: # 이벤트 루프 시작 try: loop.run_forever() # 이벤트 루프를 종료하지 않고 계속 유지 except (KeyboardInterrupt, SystemExit): print("이벤트 루프 종료 중...") if __name__ == "__main__": if sys.platform == "win32": asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) # Windows에서 SelectorEventLoop 사용 설정 asyncio.run(main())