""" 동행복권(dhlottery.co.kr) 로또 6/45 자동 구매 스크립트 - 매주 금요일 자동 실행 (cron/스케줄러 연동) - 5게임 자동 구매 - Selenium 기반 웹 자동화 사전 준비: pip install selenium Chrome 브라우저 + ChromeDriver 설치 필요 """ import os import sys import time import json import logging import urllib.request from datetime import datetime # .env 파일 자동 로드 try: from dotenv import load_dotenv load_dotenv() except ImportError: pass from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.chrome.service import Service from selenium.webdriver.chrome.options import Options from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.keys import Keys # ───────────────────────────────────────────── # 설정 # ───────────────────────────────────────────── CONFIG = { "USER_ID": os.environ.get("LOTTO_USER_ID", ""), "USER_PW": os.environ.get("LOTTO_USER_PW", ""), "BUY_COUNT": 1, # 구매 게임 수 (1~10) "HEADLESS": True, # True: 브라우저 창 숨김, False: 브라우저 창 표시 "LOG_FILE": "logs/lotto_log.json", "TELEGRAM_BOT_TOKEN": os.environ.get("TELEGRAM_BOT_TOKEN", ""), "TELEGRAM_CHAT_ID": os.environ.get("TELEGRAM_CHAT_ID", ""), } # 로깅 설정 logging.basicConfig( level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s", handlers=[ logging.StreamHandler(), logging.FileHandler("logs/lotto_auto.log", encoding="utf-8"), ], ) logger = logging.getLogger(__name__) def create_driver(): """Chrome WebDriver 생성""" options = Options() # CI 환경에서 setup-chrome이 설치한 Chrome 바이너리 경로 지정 chrome_bin = os.environ.get("CHROME_BIN", "") if chrome_bin: options.binary_location = chrome_bin if CONFIG["HEADLESS"]: options.add_argument("--headless=new") options.add_argument("--no-sandbox") options.add_argument("--disable-dev-shm-usage") options.add_argument("--disable-gpu") options.add_argument("--disable-software-rasterizer") options.add_argument("--remote-debugging-port=9222") options.add_argument("--user-data-dir=/tmp/chrome-user-data") options.add_argument("--window-size=1920,1080") # 자동화 탐지 우회 options.add_argument("--disable-blink-features=AutomationControlled") options.add_experimental_option("excludeSwitches", ["enable-automation"]) options.add_experimental_option("useAutomationExtension", False) driver = webdriver.Chrome(options=options) driver.execute_cdp_cmd( "Page.addScriptToEvaluateOnNewDocument", {"source": "Object.defineProperty(navigator, 'webdriver', {get: () => undefined})"}, ) driver.set_page_load_timeout(30) # 페이지 로드 최대 30초 driver.set_script_timeout(30) # JS 실행 최대 30초 driver.implicitly_wait(5) return driver def login(driver): """동행복권 사이트 로그인""" from selenium.common.exceptions import TimeoutException logger.info("로그인 시도 중...") try: driver.get("https://www.dhlottery.co.kr/login") except TimeoutException: logger.warning("로그인 페이지 로드 타임아웃 — 로드된 부분으로 계속 진행") time.sleep(2) # 아이디/비밀번호 입력 wait = WebDriverWait(driver, 10) id_input = wait.until(EC.element_to_be_clickable((By.ID, "inpUserId"))) id_input.click() id_input.send_keys(CONFIG["USER_ID"]) pw_input = wait.until(EC.element_to_be_clickable((By.ID, "inpUserPswdEncn"))) pw_input.click() pw_input.send_keys(CONFIG["USER_PW"]) # 로그인 버튼 클릭 login_btn = wait.until(EC.element_to_be_clickable((By.ID, "btnLogin"))) login_btn.click() # /login이 URL에서 완전히 사라질 때까지 대기 (최대 15초) try: WebDriverWait(driver, 15).until(lambda d: "/login" not in d.current_url) except: pass logger.info(f"로그인 후 URL: {driver.current_url}") # 로그인 성공 확인 (URL이 /login에서 벗어나면 성공) if "/login" in driver.current_url: logger.error("로그인 실패! 아이디/비밀번호를 확인하세요.") return False logger.info("로그인 성공!") return True def check_balance(driver): """예치금 잔액 확인""" driver.get("https://www.dhlottery.co.kr/mypage/home") time.sleep(2) try: balance_elem = driver.find_element(By.CSS_SELECTOR, "#totalAmt") balance_text = balance_elem.text.replace(",", "").replace("원", "").strip() balance = int(balance_text) if balance_text.isdigit() else 0 logger.info(f"현재 예치금 잔액: {balance:,}원") return balance except Exception as e: logger.warning(f"잔액 확인 실패: {e}") return -1 def buy_lotto(driver, game_count=5): """ 로또 6/45 자동 구매 game_count: 구매할 게임 수 (1~10) """ logger.info(f"로또 {game_count}게임 자동 구매 시작...") # 로또 구매 페이지 이동 (타임아웃 시 로드된 부분으로 계속 진행) from selenium.common.exceptions import TimeoutException try: driver.get("https://ol.dhlottery.co.kr/olotto/game/game645.do") except TimeoutException: logger.warning("페이지 로드 타임아웃 — 로드된 부분으로 계속 진행") time.sleep(2) # iframe 전환 (로또 구매 페이지는 iframe 내부에 있음) try: wait = WebDriverWait(driver, 10) def close_layer_alert_if_present(timeout_s: float = 1.5) -> bool: """