728x90
SMALL
Selenium을 활용한 웹 자동화 - 메뉴 접속 후 캡처 및 Word 문서 저장
1. Selenium이란?
Selenium은 웹 애플리케이션을 자동화하는 오픈소스 도구로, 주로 테스트 자동화 및 데이터 크롤링에 사용됩니다.
2. 주요 기능
- 로그인 자동화
- 특정 메뉴 탐색 후 버튼 클릭
- 화면 캡처 후 Word 문서 저장
3. 사용한 함수 정리
함수명 | 설명 |
handle_alert() | 팝업 알림이 발생하면 자동으로 닫음 |
wait_for_loading_to_complete() | 로딩 이미지가 사라질 때까지 대기 |
main() | 전체 실행 과정 수행 |
4. 실행 방법
- Selenium 설치
bashpip install selenium python-docx
- 크롬 드라이버 다운로드 및 설정
- Python 코드 실행
5. 결과물
실행이 완료되면 메뉴별 화면이 캡처되어 Word 문서로 저장됩니다. 🚀
6. 전체 코드
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.alert import Alert
import time
import os
import re
from docx import Document
from docx.shared import Inches
from docx.enum.section import WD_ORIENT
from docx.shared import Pt
from datetime import datetime
# ✅ 알림창 처리 함수
def handle_alert(driver, pgmid):
try:
alert = Alert(driver)
print(f"ALERT TEXT : {alert.text} - {pgmid}")
alert.accept()
except Exception:
pass # 알림창이 없으면 예외 무시
# ✅ 로딩 완료 대기 함수
def wait_for_loading_to_complete(driver, timeout=360):
try:
WebDriverWait(driver, timeout).until(
EC.invisibility_of_element_located((By.ID, "이미지ID")) # 로딩 이미지 ID
)
except Exception:
print(f"⚠️ 로딩 이미지가 너무 오래 지속됩니다.")
return False
return True
# ✅ 메인 실행 함수
def main():
now = datetime.now()
URL = "사이트URL"
SYS_NAME = "시스템이름"
SYS_SNAME = "시스템약어"
ifile_path = r"C:\입력파일경로.txt" # PGM_ID:PGM_NAME 형식
ofile_path = f"C:\{SYS_NAME} ({SYS_SNAME}) {now.year}_{now.month}_{now.day} {now.hour}_{now.minute}_{now.second}.docx"
ID = "아이디"
PASSWORD = "비밀번호"
driver = webdriver.Chrome()
driver.maximize_window()
driver.get(URL)
time.sleep(2)
# ✅ 로그인 처리
obj_id = driver.find_element(By.CSS_SELECTOR, "[id*='form.edt_userId:input']")
actions = ActionChains(driver)
actions.move_to_element(obj_id).click().perform()
obj_id.clear()
obj_id.send_keys(ID)
obj_pass = driver.find_element(By.CSS_SELECTOR, "[id*='form.edt_password:input']")
actions.move_to_element(obj_pass).click().perform()
obj_pass.send_keys(PASSWORD)
login_button = driver.find_element(By.CSS_SELECTOR, "[id*='form.btn_login']")
login_button.click()
time.sleep(1)
# ✅ Word 문서 생성
doc = Document()
heading = doc.add_heading(f"{SYS_NAME} 시스템 사용자 매뉴얼 ({SYS_SNAME})", level=1)
run = heading.runs[0]
run.font.size = Pt(24)
doc.add_page_break()
section = doc.sections[0]
section.orientation = WD_ORIENT.LANDSCAPE
# ✅ 메뉴 목록 가져오기
middle_grid_pattern = re.compile(r"메뉴경로")
middle_grid_rows = driver.find_elements(By.CSS_SELECTOR, "[id^='메뉴경로']")
codes = [el.get_attribute("id") for el in middle_grid_rows if middle_grid_pattern.match(el.get_attribute("id"))]
for code in codes:
up_menu_choice = driver.find_element(By.ID, code)
up_menu_name = up_menu_choice.text
up_menu_choice.click()
time.sleep(1)
grid_rows = driver.find_elements(By.CSS_SELECTOR, "[id^='메뉴경로']")
pattern = re.compile(r"메뉴경로")
filtered_ids = [el.get_attribute("id") for el in grid_rows if pattern.match(el.get_attribute("id"))]
for element_id in filtered_ids:
menu_choice = driver.find_element(By.ID, element_id)
menu_name = menu_choice.text
menu_choice.click()
time.sleep(1)
handle_alert(driver, "")
wait_for_loading_to_complete(driver)
# ✅ 버튼 정보 가져오기
btn_text_list = []
btn_elements = driver.find_elements(By.CSS_SELECTOR, "div[id^='메뉴경로'] .Button")
for btn in btn_elements:
if len(btn.text.strip()) > 0 and btn.text.strip() not in btn_text_list:
btn_text_list.append(btn.text.strip())
search_button = next((btn for btn in btn_elements if btn.text.strip() == "조회"), None)
if search_button:
search_button.click()
time.sleep(0.5)
handle_alert(driver, "")
wait_for_loading_to_complete(driver)
# ✅ 화면 캡처
screenshot_path = f"{menu_name}_screenshot.png"
driver.save_screenshot(screenshot_path)
doc.add_paragraph(f"프로그램 : {up_menu_name} [{menu_name}]")
doc.add_picture(screenshot_path, width=Inches(10))
doc.add_paragraph("* 개요 : ")
doc.add_paragraph("* 기능 : ")
doc.add_paragraph(f" - {', '.join(btn_text_list)}")
doc.add_page_break()
doc.save(ofile_path)
os.remove(screenshot_path)
time.sleep(0.5)
up_menu_choice.click()
doc.save(ofile_path)
time.sleep(5)
driver.quit()
if __name__ == "__main__":
main()
7. 코드 설명
메뉴리스트를 조회하기 위해 정규식으로 메뉴리스트의 패턴을 가져와서 비슷한 형태의 div id를 모두 뽑아와서 패턴에 맞는 실제 메뉴 ID의 리스트를 생성한다.
아래와 같은 방식으로 대분류, 중분류, 소분류의 메뉴의 리스트들을 모두 찾아서 접근 할수가 있다.
```python
import re
from selenium import webdriver
from selenium.webdriver.common.by import By
# 정규식을 사용하여 특정 패턴을 가진 ID 찾기
middle_grid_pattern = re.compile(
r"mainframe\.vFrameSet\.frameTop\.form\.div_topMenu\.form\.btn_topMenu_.*:icontext$"
)
# Selenium으로 해당하는 ID 찾기
driver = webdriver.Chrome()
driver.get("https://example.com") # 웹사이트 URL 변경 필요
middle_grid_rows = driver.find_elements(By.CSS_SELECTOR,
"[id^='mainframe.vFrameSet.frameTop.form.div_topMenu.form.btn_topMenu_']")
codes = [el.get_attribute("id") for el in middle_grid_rows if middle_grid_pattern.match(el.get_attribute("id"))]
728x90
LIST