ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Python, Selenium] 파이썬, 셀레늄을 이용한 로또 자동 구매 프로그램
    코딩/Python 2022. 7. 1. 14:37
    반응형

    매주 사야지 사야지 하다가도 까먹고 안 사는 경우가 더 많아서

    셀레늄으로 한번 만들어보았다.

     

    구동을 위한 준비물로는

    당연히 python (3.8 이상 버전을 권장)

    셀레늄 버전 4 이상 (pip로 그냥 설치하면 되는듯)

    크롬드라이버 자동 업데이트를 위해서 webdriver_manager 패키지도 필요하다.

     

    크롬드라이버는 자동설치 기능을 이용하기 때문에 따로 설치안해주어도 된다.

     

    주의점으로는 윈도우 환경에서만 작동한다. (테스트는 안해봤지만 맥에서도 될듯)

     

    기능은 크게 세가지

     

    1. 예치금 잔고 체크 기능 (check_deposit 함수)

    현재 예치금을 확인해서 텔레그램 메시지로 보내준다. 

     

    2. 예치금 충전 (charge_deposit 함수)

    예치금 충전 버튼을 눌러서 입금계좌를 텔레그램으로 보내준다. 

    충전 금액은 기본값인 2만 원으로 충전되게 설정 

     

    3. 로또 구매 (buy_lotto 함수)

    모드 지정에 따라 자동, 수동, 일부 수동 방식으로 구매 

     

     

    나는 텔레그램 토큰 정보 같은걸 config파일로 만들어서 사용하고 있다.

    재활용이 편하게 전에 만들어둔걸 이렇게 쓰는데 꼭 이렇게 할 필요는 없을 것 같다. 

     

    read_config 함수의 config_data 변수를 참조해서 해당 데이터를 코드에 바로 입력해서 사용해도 무방.

    사용하지 않는 기능 정보는(셀레늄 리모트, 텔레그램 불필요할 경우 토큰 정보 등) 적당히 아무 값이나 넣으면 상관없음. 

    봇 초기화를(bot_init함수) 안 하면 텔레그램 사용 없이 화면 출력 모드로 구동된다.

     

    config.ini파일의 형태는 다음과 같다.

    [server]
    host = 셀레늄 리모트 서버 주소 
    
    [user]
    id = 동행복권사이트 아이디
    pwd = 비밀번호
    
    [telegram]
    token = 텔레그램봇 토큰
    chat_id = 수신받을 내 챗 아이디

     

    아래 첨부된 코드는 그 자체로 직접 구동 시 예치금 잔고 체크 및 일정 금액 이하일 경우 충전하도록 되어 있다.

    그대로 사용해도 되고, 필요에 따라 수정하면 된다. 

     

    나는 아래처럼 별도 구매 파일을 작성해서 사용 중이다. 

    import pylotto
    
    conf = pylotto.read_config('config.ini')
    
    driver_type = 'local'
    lotto = pylotto.DhLottery()
    lotto.driver_init(driver_type, conf['host'])
    lotto.bot_init(conf['token'], conf['chat_id'])
    
    lotto.login(conf['uid'], conf['passwd'])
    lotto.buy_lotto('manual', 3, [1, 2, 3, 4, 5, 6])
    lotto.buy_lotto('auto', 2)
    
    lotto.driver.quit()

    자동으로 구매할 경우

    buy_lotto('auto', 수량)

     

    수동은

    buy_lotto('manual', 수량, 내가 원하는 번호 리스트)

     

    혼합방식은

    buy_lotto('mixed', 수량, 일부 번호 리스트)

     

     

    메인코드는 아래와 같다.


    from selenium import webdriver
    from selenium.webdriver.support.ui import Select
    from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
    from selenium.webdriver.common.by import By
    from selenium.webdriver.chrome.service import Service
    from webdriver_manager.chrome import ChromeDriverManager
    import configparser
    import time
    import telegram
    
    
    class DhLottery:
        def __init__(self):
            self.driver = None
            self.deposit = None
            self.bot = None
            self.chat_id = None
    
        def driver_init(self, _mode='local', _host=None):
            _driver = None
            if _mode == 'local':
                # 크롬드라이버 자동 설치
                _driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
            elif _mode == 'remote':
                _driver = webdriver.Remote(_host, DesiredCapabilities.CHROME)
            _driver.implicitly_wait(5)
            self.driver = _driver
    
        def bot_init(self, _token, _chat_id):
            self.bot = telegram.Bot(token=_token)
            self.chat_id = _chat_id
    
        def login(self, _uid, _passwd):
            # 로그인 페이지 이동
            _url = 'https://dhlottery.co.kr/user.do?method=login&returnUrl='
            _driver = self.driver
            _driver.get(url=_url)
    
            _driver.find_element(By.XPATH, '//input[@name="userId"]').send_keys(_uid)  # 아이디 입력
            _driver.find_element(By.XPATH, '//input[@name="password"]').send_keys(_passwd)  # 비밀번호 입력
            _driver.execute_script("javascript:check_if_Valid3();")  # 로그인 실행
    
            time.sleep(3)
            self.remove_popup()  # 팝업창 제거함수 호출
    
        def check_deposit(self):
            # 마이페이지로 이동
            _driver = self.driver
            _driver.get(url='https://dhlottery.co.kr/userSsl.do?method=myPage')
    
            # 예치금 금액 읽음
            _deposit = _driver.find_element(By.XPATH, '//p[@class="total_new"]/strong').text
    
            if self.bot is not None:
                self.send_telegram(f'잔고 : {_deposit}원')
            _deposit = _deposit.replace(',', '')  # 천단위 쉼표 제거
    
            print(f'잔액: {_deposit}')
    
            self.deposit = int(_deposit)
    
        def remove_popup(self):
            _driver = self.driver
    
            # 생성된 팝업창을 모두 닫음
            _tabs = _driver.window_handles
            while len(_tabs) != 1:
                _driver.switch_to.window(_tabs[1])
                _driver.close()
                _tabs = _driver.window_handles
    
            # 첫 창으로 돌아간다
            _driver.switch_to.window(_tabs[0])
    
        def send_telegram(self, _msg):
            _msg = '<로또>\n' + _msg
            self.bot.sendMessage(chat_id=self.chat_id, text=_msg)
    
        def send_result(self, _data):
            _msg = '구매성공!!\n' + '=' * 15
            for _d in _data:
                _msg = _msg + '\n' + ','.join(_d)
            print(_msg)
            self.send_telegram(_msg)
    
        def charge_deposit(self):
            # 예치금 충전 페이지로 이동
            _url = 'https://dhlottery.co.kr/payment.do?method=payment'
            _driver = self.driver
            _driver.get(url=_url)
    
            time.sleep(1)
            _driver.execute_script("nicepayStart();")  # 충전버튼 클릭
    
            time.sleep(1)
            # 충전금액
            _amount = _driver.find_element(By.XPATH, '//div[@class="contents_wrap contents_result_payment"]'
                                                     '/div/table/tbody/tr[2]/td').text
            # 입금계좌
            _account = _driver.find_element(By.XPATH, '//span[@class="pay_lt"]').text
    
            # 충전 금액, 계좌정보 출력하거나 텔레그램 전송
            _msg = f'예치금 충전\n{_account}\n{_amount}'
            if self.bot is not None:
                self.send_telegram(_msg)
            else:
                print(_msg)
    
        def buy_lotto(self, _mode, _amount, _nums=None):
            # 메인 페이지로 이동
            _url = 'https://dhlottery.co.kr/common.do?method=main'
            _driver = self.driver
            _driver.get(url=_url)
    
            # 팝업창 닫음
            time.sleep(3)
            self.remove_popup()
    
            # 로또 구매 페이지로 이동
            _driver.execute_script('javascript:goLottoBuy(2);')
    
            # 생성된 구매 페이지로 전환
            time.sleep(3)
            _tabs = _driver.window_handles
            _driver.switch_to.window(_tabs[1])
    
            # 내부 iframe으로 전환
            _content = _driver.find_element(By.TAG_NAME, "iframe")
            _driver.switch_to.frame(_content)
    
            if _mode == 'manual':  # 수동모드
                for _n in _nums:
                    _driver.find_element(By.XPATH, f'//label[@for="check645num{str(_n)}"]').click()
    
            elif _mode == 'auto':  # 자동모드
                _driver.find_element(By.XPATH, '//label[@for="checkAutoSelect"]').click()
    
            elif _mode == 'mixed':  # 혼합모드 (숫자 일부 지정, 나머지 자동)
                for _n in _nums:
                    _driver.find_element(By.XPATH, f'//label[@for="check645num{str(_n)}"]').click()
                _driver.find_element(By.XPATH, '//label[@for="checkAutoSelect"]').click()
    
            # 수량 변경
            _select = Select(_driver.find_element(By.XPATH, '//select[@id="amoundApply"]'))
            _select.select_by_value(str(_amount))
    
            # 수량 입력 확인
            _driver.find_element(By.XPATH, '//input[@id="btnSelectNum"]').click()
    
            # 구매하기 버튼
            _driver.find_element(By.XPATH, '//input[@id="btnBuy"]').click()
    
            # 최종 구매 확인
            _driver.execute_script("javascript:closepopupLayerConfirm(true);")
    
            # 구매 번호 불러옴
            time.sleep(3)
            _res1 = _driver.find_elements(By.XPATH, '//ul[@id="reportRow"]/li')
    
            # 구매된 번호들을 인식
            _result = list()
            for _r1 in _res1:
                _selected = list()
                _res2 = _r1.find_elements(By.XPATH, 'div[@class="nums"]/span')
                for _r2 in _res2:
                    _selected.append(_r2.text)
                _result.append(_selected)
    
            # 인식된 번호 텔레그램 전송
            if self.bot is not None:
                self.send_result(_result)
            else:
                print(_result)
    
            # iframe에서 기본 창으로 다시 변경
            _driver.switch_to.default_content()
    
    
    def read_config(_conf_file):
        _config = configparser.ConfigParser()
        _config.read(_conf_file)
    
        _config_data = {
            'host': _config['server']['host'],  # Selenium Remote 주소
            'uid': _config['user']['id'],  # 동행복권 아이디
            'passwd': _config['user']['pwd'],  # 동행복권 비밀번호
            'token': _config['telegram']['token'],  # 텔레그램봇 토큰
            'chat_id': _config['telegram']['chat_id']  # 텔레그램 전송받을 챗아이디
        }
    
        return _config_data
    
    
    if __name__ == '__main__':
        conf = read_config('config.ini')
    
        driver_type = 'local'
        lotto = DhLottery()
        lotto.driver_init(driver_type, conf['host'])
        lotto.bot_init(conf['token'], conf['chat_id'])  # 텔레그램 불필요시 비활성화
    
        lotto.login(conf['uid'], conf['passwd'])
    
        time.sleep(1)
        lotto.check_deposit()
        if lotto.deposit <= 10000:
            lotto.charge_deposit()
    
        lotto.driver.quit()
    반응형
Designed by Tistory.