본문으로 바로가기

[discord.py 2.0] lottery.py 소스코드 정리

category 정보/Discord Bot 2022. 9. 27. 12:37
728x90
반응형

이전글보기

[정보/Discord Bot] - [discord.py 2.0] 14. 오류 발생 시 예외 처리하기

[정보/Discord Bot] - [discord.py 2.0] 15. 로또복권 정보 출력하기 (beautifulsoup4 library) - #1 사전 library 준비

[정보/Discord Bot] - [discord.py 2.0] 15. 로또복권 정보 출력하기 (beautifulsoup4 library) - #2 최신 로또 번호 파싱하기

[정보/Discord Bot] - [discord.py 2.0] 15. 로또복권 정보 출력하기 - #3 모든 당첨내역 다운로드하기

[정보/Discord Bot] - [discord.py 2.0] 15. 로또복권 정보 출력하기 - #4 데이터로부터 데이터 가공하기


이번 포스팅에서는 이후 기능추가에 앞서 추가했던 로또 기능에서의 임시 명령어들을 정리할겁니다.

https://github.com/aochfl/ChoRi_TestBot/commit/62004fe8d6a19b1673f232b5c4c682a05a626660?diff=split 

정확한 소스코드는 위 commit 정보를 확인해주세요.

 

우선 LotteryFunction 생성자입니다.

변경 전(좌) / 변경 후(우)

우 19~22 : 최신 정보를 파싱(parse_newest)/ 리스트 확인 및 다운로드(download_total) / 계산(calculate_list) 을 일괄적으로 처리할수 있도록 check_list 함수를 추가하였으며, 이를 기존 parse_newest 대신 호출해줍니다

 

변경 전(좌) / 변경 후(우)

전체 로또 내역이 저장된 파일경로를 저장하는 self.listFilePath 변수는 calculate_list 함수 안에서만 변경이 발생하므로, 함수내부로 이동하였습니다.

 

변경 전(좌) / 변경 후(우)

self.mCalculated 변수는 현재 다운로드 되어있는 로또 리스트가 계산이 되어있는지 여부를 저장해놓는 변수입니다.
마찬가지로 false 가 되는 경우는 Bot이 최초로 동작하는 경우나, 리스트가 새로 다운로드 되는 경우밖에 없으니 download_total 함수 안으로 이동하였습니다.

 

변경 전(좌) / 변경 후(우)

calculate_list 함수의 경우 여러번 호출되어도 반복하여 계산하지 않도록 self.mCalculated 변수가 False 로 세팅되어있을때만 계산하도록 if 조건문을 추가합니다

 

변경 전(좌) / 변경 후(우)

!로또 명령어 호출시 parse_newest 함수 호출 대신, 일괄동작이 포함된 check_list 함수를 호출하도록 변경하고,

임시로 추가해놓은 다운,계산 명령어는 삭제하였습니다.

 

전체 소스코드입니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import os
import glob
import discord
from discord.ext import commands
from bs4 import BeautifulSoup
import urllib.request
 
 
class LotteryFunction:
    def __init__(self):
        self.lastGameCount = None  # 1033
        self.lastGameDate = None  # (2022년 09월 17일 추첨)
        self.lastGameNumbers = []
        self.listFilePath = ""
        self.mCounterList = {}  # 로또 숫자 별 추첨 횟수
        self.mCalculated = False  # 리스트에 대하여 계산여부 저장
        self.check_list()
 
    def check_list(self):
        self.parse_newest()
        self.download_total()
        self.calculate_list()
 
    # 현재 회차 정보 파싱
    def parse_newest(self):
        self.lastGameNumbers.clear()
        url = 'https://dhlottery.co.kr/gameResult.do?method=byWin'
        webpage = urllib.request.urlopen(url)
        soup = BeautifulSoup(webpage, 'html.parser')
        self.lastGameCount = soup.select_one('div.win_result > h4 > strong').get_text().split("회")[0]
        self.lastGameDate = soup.select_one('div.win_result > p').get_text()
        numberList = soup.select('div.win_result > div > .num > p .ball_645')
        for number in numberList:
            self.lastGameNumbers.append(number.get_text())
        self.listFilePath = f'./lottery{self.lastGameCount}.xls'
 
    def delete_list(self, filename: str):
        for name in glob.glob(filename):
            print(name + " 파일이 삭제되었습니다")
            os.remove(name)
 
    # 모든 추첨 번호 다운 로드
    def download_total(self):  # list 를 새로 다운받았을 경우 true 반환
        if os.path.isfile(self.listFilePath):
            print("최신 로또결과가 이미 존재합니다\n")
        else:
            self.delete_list('*[0-9].xls')
            start_count = 1
            url = f'https://dhlottery.co.kr/gameResult.do?method=allWinExel&gubun=byWin&nowPage=1&' \
                  f'drwNoStart={start_count}&drwNoEnd={self.lastGameCount}'
            urllib.request.urlretrieve(url, self.listFilePath)
            self.mCalculated = False
 
    # 다운받은 리스트를 통해 계산
    def calculate_list(self):
        if os.path.isfile(self.listFilePath):
            if not self.mCalculated:
                for idx in range(146):
                    self.mCounterList[str(idx)] = 0  # 리스트 초기화
                default_row = 3   # 로또 list 에서 추첨 번호가 시작 하는 행
                list_xml = open(self.listFilePath, encoding='cp949')  # 저장된 list 불러오기
                soup = BeautifulSoup(list_xml, 'html.parser')  # 데이터 파싱
                total_info = soup.findAll('tr')
                for row in range(default_row, len(total_info)):
                    row_data = total_info[row].findAll('td')
                    max_col = len(row_data)
                    for col in range(max_col-7, max_col):
                        # 각 숫자가 뽑힌 횟수 계산
                        self.mCounterList[row_data[col].text] += 1
                print("로또 번호 리스트 계산완료\n")
                self.mCalculated = True
        else:
            self.download_total()
            self.calculate_list()
 
 
class Lottery(commands.Cog):
    def __init__(self, app):
        self.app = app
        self.lottery = LotteryFunction()
 
    @commands.command(name="로또")
    async def lottery(self, ctx):
        self.lottery.check_list()
        embed = discord.Embed(title="로또 추첨 번호", description="최근 로또 번호를 출력합니다", colour=0xffffff)
        embed.set_thumbnail(url="https://dhlottery.co.kr/images/layout/logo-header.png")
        # 데이터로부터 추첨날짜 확인
        embed.add_field(name="추첨날짜", value=self.lottery.lastGameDate, inline=True)
        # 데이터로부터 회차 확인
        embed.add_field(name="회차", value=self.lottery.lastGameCount+"회", inline=True)
        embed.add_field(name="추첨번호", value=self.lottery.lastGameNumbers, inline=False)
        await ctx.send(embed=embed)
 
 
async def setup(app):
    await app.add_cog(Lottery(app))
 
cs

 

이후 포스팅에서는 계산된 데이터를 정리하여 출력하는 동작을 추가할 예정입니다.


포스팅에 사용된 모든 소스코드는 아래 Github에서 확인하실 수 있습니다.

https://github.com/aochfl/ChoRi_TestBot

 

GitHub - aochfl/ChoRi_TestBot

Contribute to aochfl/ChoRi_TestBot development by creating an account on GitHub.

github.com


참고자료

https://discord.com/developers/docs/reference - ( Discord Developer API )

https://discordpy.readthedocs.io/en/latest/index.html  -  ( discord.py library 문서 )

 

728x90
반응형