feat: 안전한 클릭 및 레이어 알림 처리 개선
Some checks failed
로또 자동 구매 / buy (push) Failing after 14m49s

- 레이어 알림이 존재할 경우 자동으로 닫는 기능을 보강하여 클릭 시 간섭 방지
- 클릭 시 팝업이 가로채는 경우를 처리하는 safe_click 함수 추가
- 자동번호 선택 및 구매 버튼 클릭 시 안전한 클릭 로직 적용
- 코드 가독성을 높이기 위해 주석 추가
This commit is contained in:
hyeonggil
2026-03-27 23:53:22 +09:00
parent d49b6cfb30
commit 499237bb35

View File

@@ -228,9 +228,55 @@ def buy_lotto(driver, game_count=5):
except Exception:
return False
def ensure_no_layer_alert(max_rounds: int = 3) -> None:
"""popupLayerAlert가 떠 있으면 닫히는 것까지 보장(짧게 재시도)."""
for _ in range(max_rounds):
closed = close_layer_alert_if_present(timeout_s=0.6)
try:
WebDriverWait(driver, 1.2).until(
EC.invisibility_of_element_located((By.ID, "popupLayerAlert"))
)
return
except Exception:
if not closed:
return
time.sleep(0.2)
def safe_click(locator, timeout_s: float = 10, retries: int = 2) -> None:
"""클릭이 팝업에 가로채이면 popupLayerAlert 닫고 재시도."""
from selenium.common.exceptions import ElementClickInterceptedException
last_exc = None
for _ in range(retries + 1):
ensure_no_layer_alert()
el = WebDriverWait(driver, timeout_s).until(EC.element_to_be_clickable(locator))
try:
el.click()
return
except ElementClickInterceptedException as e:
last_exc = e
# 팝업이 클릭을 가로채는 경우가 대부분이라 닫고 재시도
close_layer_alert_if_present(timeout_s=0.8)
time.sleep(0.3)
except Exception as e:
last_exc = e
break
# 마지막 fallback: JS click
try:
ensure_no_layer_alert()
el = WebDriverWait(driver, timeout_s).until(EC.presence_of_element_located(locator))
driver.execute_script("arguments[0].click();", el)
return
except Exception:
if last_exc:
raise last_exc
raise
# 첫 상호작용 전에 레이어 알림이 떠 있으면 먼저 닫기
if close_layer_alert_if_present():
logger.info("초기 popupLayerAlert 감지 — 닫기 처리 완료")
ensure_no_layer_alert()
# 모든 레이어 팝업을 JS로 직접 숨기기 (z-index 오버레이 완전 제거)
driver.execute_script("""
@@ -242,16 +288,14 @@ def buy_lotto(driver, game_count=5):
time.sleep(0.5)
logger.info("팝업 레이어 숨김 처리 완료")
# "자동" 탭 선택 — onclick 함수(selectWayTab)를 직접 호출
# (간헐적으로 popupLayerAlert가 클릭을 가로채므로 전/후로 닫기 처리 + 1회 재시도)
for attempt in range(2):
close_layer_alert_if_present(timeout_s=0.5)
# "자동" 탭 선택 (id=num2). 팝업이 클릭을 가로채는 케이스 방지.
try:
safe_click((By.ID, "num2"), timeout_s=10, retries=2)
except Exception:
# fallback: 함수 직접 호출
ensure_no_layer_alert()
driver.execute_script("selectWayTab(1);")
time.sleep(1)
if not close_layer_alert_if_present(timeout_s=0.5):
break
logger.info("자동 탭 선택 중 popupLayerAlert 재발 — 닫기 후 재시도")
time.sleep(0.5)
time.sleep(1)
# 게임 수 설정 (드롭다운에서 선택)
from selenium.webdriver.support.ui import Select
@@ -263,14 +307,12 @@ def buy_lotto(driver, game_count=5):
except Exception:
# 드롭다운이 없는 경우 자동번호 버튼을 game_count번 클릭
for i in range(game_count):
auto_select_btn = driver.find_element(By.ID, "btnSelectNum")
auto_select_btn.click()
safe_click((By.ID, "btnSelectNum"), timeout_s=10, retries=2)
time.sleep(0.5)
# "자동번호 선택" 버튼 클릭
try:
select_num_btn = driver.find_element(By.ID, "btnSelectNum")
select_num_btn.click()
safe_click((By.ID, "btnSelectNum"), timeout_s=10, retries=2)
time.sleep(1)
except:
pass
@@ -283,14 +325,20 @@ def buy_lotto(driver, game_count=5):
buy_btn = wait.until(
EC.element_to_be_clickable((By.ID, "btnBuy"))
)
buy_btn.click()
try:
buy_btn.click()
except Exception:
safe_click((By.ID, "btnBuy"), timeout_s=10, retries=2)
time.sleep(2)
# 구매 확인 팝업 "확인" 클릭
confirm_btn = wait.until(
EC.element_to_be_clickable((By.CSS_SELECTOR, "#popupLayerConfirm input[value='확인']"))
)
confirm_btn.click()
try:
confirm_btn.click()
except Exception:
safe_click((By.CSS_SELECTOR, "#popupLayerConfirm input[value='확인']"), timeout_s=10, retries=2)
time.sleep(3)
logger.info("구매 요청 완료! 구매 결과를 확인합니다...")