๐Ÿค‘ Lotto ๊ตฌ๋งค ์ž๋™ํ™”

 

0. ๋“ค์–ด๊ฐ€๊ธฐ ์ „

๐Ÿ› ๏ธ ์ž‘์—…์˜ ์ˆœ์„œ

  1. Python ํ”„๋กœ๊ทธ๋žจ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค.
  2. crontab์— ์ž‘์—… ๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค.

โœ… Github Actions vs crontab(Windows: ์ž‘์—… ์Šค์ผ€์ค„๋Ÿฌ)
๊ณ„์ • ์ •๋ณด๋ฅผ ํŠน์ • ์„œ๋ฒ„์— ์˜ฌ๋ฆฌ๋Š” ๊ฒƒ์ด ๋ถˆ์•ˆํ•ด์„œ crontab์„ ์‚ฌ์šฉํ•˜๊ธฐ๋กœ ๊ฒฐ์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.

1. Python ํ”„๋กœ๊ทธ๋žจ ์ž‘์„ฑ

1.1 Anaconda ์„ค์น˜ ๋ฐ ํ™˜๊ฒฝ๊ตฌ์„ฑ

  1. ์•„๋ž˜ ๋งํฌ๋ฅผ ํด๋ฆญํ•˜์—ฌ Anaconda ์„ค์น˜ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค.
    ๐Ÿ”—Anaconda
    macOS ์„ค์น˜ ์‹œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•  ๊ฒฝ์šฐ Install for me only ์˜ต์…˜์œผ๋กœ ์„ค์น˜๋ฅผ ์ง„ํ–‰ํ•ฉ๋‹ˆ๋‹ค.
    ๐Ÿ”—Installing-on-macOS

  2. ๊ฐ€์ƒํ™˜๊ฒฝ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

     (base) edward@Edwards-MacBook-Pro conda create -n ENVNAME python=VERSION
     (base) edward@Edwards-MacBook-Pro conda activate ENVNAME
     (ENVNAME) edward@Edwards-MacBook-Pro pip install jupyter
     (ENVNAME) edward@Edwards-MacBook-Pro pip install nbconvert
     (ENVNAME) edward@Edwards-MacBook-Pro pip install selenium
    
  3. Jupyter notebook์„ ์‹คํ–‰ํ•˜์—ฌ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค.
    ๋ฒˆํ˜ธ๋ณ„ ํ†ต๊ณ„ ์ •๋ณด๋ฅผ ํฌ๋กค๋ง(๐Ÿ”—๋ฒˆํ˜ธ๋ณ„ ํ†ต๊ณ„)ํ•˜์—ฌ ๋ฒˆํ˜ธ๋ณ„๋กœ ๊ฐ€์ค‘์น˜๋ฅผ ๋ถ€์—ฌํ–ˆ๊ณ , ๊ฐ€์ค‘์น˜๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๋ฒˆํ˜ธ๋ฅผ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.
    โ—๏ธ Account Info ์ฃผ์„ ํ•˜๋‹จ์— ๊ณ„์ • ์ •๋ณด๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”.

     (ENVNAME) edward@Edwards-MacBook-Pro jupyter notebook
    
     import random
     from selenium import webdriver
     from selenium.webdriver.chrome.options import Options
     from selenium.webdriver.support.wait import WebDriverWait
     from selenium.webdriver.common.by import By
     from selenium.webdriver.support import expected_conditions as ec
     from selenium.webdriver.common.keys import Keys
    
     ###############################
     # Classes
     ###############################
     class Ball:
         def __init__(self, n, w):
             self.number = n
             self.weight = w
    
     ###############################
     # Functions
     ###############################
     # Common
     def wait_and_click(driver, xpath):
         element = WebDriverWait(driver, 10).until(
             ec.element_to_be_clickable((By.XPATH, xpath))
         ).click()
    
     def close_pop_ups(main_window):
         new_popup = WebDriverWait(driver, 3).until(ec.new_window_is_opened(main_window))
         windows = driver.window_handles
         for w in windows:
             if w != main_window[0]:
                 driver.switch_to.window(w)
                 driver.close()
                 driver.switch_to.window(main_window[0])
    
     # Lotto
     def get_num_arr(balls, total_weight):
         result = []
         while result.__len__() != 6:
             r = random.random()
             for b in balls:
                 r -= b.weight
                 if r < 0 and b not in result:
                     result.append(b)
                     break
         return result
    
     ###############################
     # Driver Options Settings
     ###############################
     options = Options()
     options.add_argument("headless")
     options.add_argument("--disable-loging")
     options.add_argument("--blink-settings=imagesEnabled=false") # Unloading Images
    
     ##############################
     # Account Info
     ##############################
     USER_ID = "user_id"
     USER_PW = "user_pw"
    
     ##############################
     # Create Session
     ##############################
     driver = webdriver.Chrome(options)
     driver.get("https://dhlottery.co.kr/user.do?method=login&returnUrl=")
     main_window = driver.window_handles
     logging.debug("[Main window name is %s..;]" %main_window)
     print("[Main window name is %s..;]" %main_window)
     print("[Create Session Completed..;]")
    
     ##############################
     # Login Process
     ##############################
     user_id = "/html/body/div[3]/section/div/div[2]/div/form/div/div[1]/fieldset/div[1]/input[1]"
     user_pw = "/html/body/div[3]/section/div/div[2]/div/form/div/div[1]/fieldset/div[1]/input[2]"
     wait_and_click(driver, user_id)
     driver.find_element(By.XPATH, user_id).send_keys(USER_ID)
     driver.find_element(By.XPATH, user_pw).send_keys(USER_PW, Keys.ENTER)
     print("[Login Completed..;]")
     # Close Pop-ups
     close_pop_ups(main_window)
    
     ##############################
     # Select Numbers
     ##############################
     driver.get("https://dhlottery.co.kr/gameResult.do?method=statByNumber")
     weights = driver.find_elements(By.XPATH, "//*[@id='printTarget']/tbody/tr/td[3]")
     balls = []
     total_weight = 0
     for i in range(0, 45):
         w = int(weights[i].text)
         balls.append(Ball(i + 1, w))
         total_weight += w
    
     for b in balls:
         b.weight = b.weight / total_weight
    
     ##############################
     # Buy 6/45 Lotto
     ##############################
     wait_and_click(driver, "//*[@id=\"gnb\"]/ul/li[1]/a")
     driver.find_element(By.XPATH, "//*[@id=\"gnb\"]/ul/li[1]/div/ul/li[1]/a").click()
     # Switch Window
     windows = driver.window_handles
     for w in windows:
         if w != main_window[0]: driver.switch_to.window(w)
     driver.switch_to.frame("ifrm_tab")
     # Execute Script
     script = ""
     for i in range(0, 5):
         selected_balls = get_num_arr(balls, total_weight)
         for ball in selected_balls:
             script += " $('#check645num%s').click();\n " %ball.number
         script += " $('#btnSelectNum').click();\n "
     script += " $('#btnBuy').click();\n "
     driver.execute_script(script)
     wait_and_click(driver, "/html/body/div[4]/div/div[2]/input[1]")
     print("[Complete All tasks]")
     driver.quit()
    
  4. ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•ด์„œ .ipynb์„ .py๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

     (ENVNAME) edward@Edwards-MacBook-Pro jupyter nbconvert --to script FILENAME.ipynb
    

2. crontab ํŽธ์ง‘

๋‹ค์Œ ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•˜์—ฌ Python ์‹คํ–‰ ๊ฒฝ๋กœ๋ฅผ ์–ป์Šต๋‹ˆ๋‹ค.
(ENVNAME) edward@Edwards-MacBook-Pro which python
๊ทธ๋ฆฌ๊ณ  ์•„๋ž˜ ๋ช…๋ น์–ด๋ฅผ ํ†ตํ•ด์„œ crontab์„ ํŽธ์ง‘ํ•ฉ๋‹ˆ๋‹ค.
(ENVNAME) edward@Edwards-MacBook-Pro sudo crontab -e
i๋ฅผ ์ž…๋ ฅํ•˜๋ฉด ํŽธ์ง‘ ๋ชจ๋“œ๋กœ ๋ณ€๊ฒฝ๋ฉ๋‹ˆ๋‹ค.
Cron Schedule ํ‘œํ˜„์‹ ์ž‘์„ฑ ํ›„ Python ์‹คํ–‰ ๊ฒฝ๋กœ๋ฅผ ๋ถ™์—ฌ๋„ฃ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์‹คํ–‰ํ•  ํŒŒ์ผ ๊ฒฝ๋กœ๋ฅผ ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค.
esc ๋ˆ„๋ฅด๋ฉด ํŽธ์ง‘ ๋ชจ๋“œ์—์„œ ๋‚˜์˜ค๊ฒŒ ๋˜๋ฉฐ :๋ฅผ ์ž…๋ ฅํ•œ ๋’ค wq(์ €์žฅ ๋ฐ ์ข…๋ฃŒ)๋ฅผ ์ž…๋ ฅํ•˜์—ฌ ํŽธ์ง‘์„ ๋งˆ๋ฌด๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

#  _______________ minute (0 - 59)
# |  _______________ hour (0 - 23)
# | |  _______________ day of the month (1 - 31)
# | | |  _______________ month (1 - 12)
# | | | |  _______________ day of the week (0 - 7)
# | | | | |
# * * * * * command to execute

# ๊ธˆ์š”์ผ ์˜คํ›„ 9์‹œ์— ์‹คํ–‰
0 9 * * 5 anaconda3/envs/ENVNAME/bin/python /Users/edward/auto/lotto.py