-
[데이터수집] 로또번호 전송봇 만들기Python/웹스크래핑.데이터수집 2021. 1. 4. 15:37
매주 토요일 저녁 8시 47분마다
동행복권 사이트(dhlottery.co.kr/common.do?method=main)에서 해당 주차 당첨번호를 확인 후 전송하는 텔레그램봇 작성
당첨번호 확인이 지연될 경우, 완료될 때까지 5분 단위로 재실행하고, 재시도하겠다는 메시지를 보낸다.
로또사이트는 참으로 친절해서 아래 url 정보만 있으면 번호를 바로 조회할 수 있다.
url = 'https://dhlottery.co.kr/gameResult.do?method=byWin&drwNo=' + 회차정보
이제 매주의 회차 정보를 구하면 된다.
로또 추첨은 매주 1회 진행하고, 그때마다 1회차씩 증가하므로
처음 시작한 1회(2002. 12. 07.) 기준으로 몇주가 지나갔는가를 계산하면 된다.
조회 대상 날짜에서 시작일을 뺀 다음, 주 단위로 환산하기 위해 7로 나누고, 거기에 첫 시작회차 숫자인 1을 더한다.
from datetime import datetime, timedelta def getWeeks(year, month, day, baseDay = datetime(2002, 12, 7)): howManyDays = datetime(year, month, day) - baseDay return int(howManyDays.days/7) + 1
예를 들어 최신 회차인 2021. 01. 02.인 경우, 시작일로부터 6601일이 경과했으므로
7로 나누면 943이 되고, 회차는 944회차가 된다.
회차를 구했으니 requests를 보내본다.
import requests baseURL = 'https://dhlottery.co.kr/gameResult.do?method=byWin&drwNo=' data = requests.get(baseURL + getWeeks(2021, 1, 2)) print(data.text) ''' <!DOCTYPE html> <html lang="ko"> <head> <meta charset="EUC-KR"> <meta id="utitle" name="title" content="동행복권"> <meta id="desc" name="description" content="동행복권 944회 당첨번호 2,13,16,19,32,33+42. 1등 총 13명, 1인당 당첨금액 1,961,836,356원."> <title>로또6/45 - 회차별 당첨번호</title> <title>동행복권</title> '''
필요한 데이터는 head 최상단에 들어있다. meta 태그에서 id desc로 검색하고, content를 얻으면 된다.
from bs4 import BeautifulSoup soup = BeautifulSoup(data.text, 'html.parser') numberData = soup.find('meta', id='desc')['content'] print(numberData) ''' 동행복권 944회 당첨번호 2,13,16,19,32,33+42. 1등 총 13명, 1인당 당첨금액 1,961,836,356원. '''
데이터를 모바일로 보낼 것이라서 줄바꿈이 들어갔으면 좋겠다.
def parse(numberData): result = numberData.replace(" 당첨번호 ", "\n") result = result.replace("+", "\n2등 보너스: ") result = result.replace(". ", ".\n") result = result.replace(", 1인당 당첨금액 ", ", 각 ") return result parsed = parse(numberData) print(parsed) ''' 동행복권 944회 2,13,16,19,32,33 2등 보너스: 42. 1등 총 13명, 각 1,961,836,356원. '''
이제 혹시 확인이 지연될 경우를 위한 에러처리를 추가한다.
아직 업데이트되지 않은 945회차 열람을 시도하면
url945 = 'https://dhlottery.co.kr/gameResult.do?method=byWin&drwNo=' + str(945) testData = requests.get(url945).text print(testData) ''' <!DOCTYPE html> <html lang="ko"> <head> <meta charset="EUC-KR"> <meta id="utitle" name="title" content="동행복권"> <meta id="desc" name="description" content="동행복권 회 당첨번호 ,,,,,+. 1등 총 명, 1인당 당첨금액 원."> <title>로또6/45 - 회차별 당첨번호</title> <title>동행복권</title> '''
해당 구간 데이터만 생략되어 리턴된다. 이 데이터를 위의 parse 함수에 넣으면 아래와 같이 된다.
print(parsed(testData)) ''' ,,,,, 2등 보너스: . 1등 총 명, 각 원. '''
이 경우는 '아직 확인되지 않았습니다'라는 결과를 리턴하는 편이 나을 것 같다.
확인에 실패한 경우 재실행을 해야하기 때문에, 완료여부를 1번째 인자에 넣어서 리턴하기로 한다.
def parse(numberData, weeks): result = numberData.replace(" 당첨번호 ", "\n") result = result.replace("+", "\n2등 보너스: ") result = result.replace(". ", ".\n") result = result.replace(", 1인당 당첨금액 ", ", 각 ") if ',,,,,' in result: result = str(weeks) + '회차는 아직 확인되지 않았습니다.' return False, result return True, result
이제 정리해서, 봇에 연결([TelegramBot] 봇 생성과 메시지전송)하고, 성공할 때까지 반복실행하도록 한다.
def getData(current=None): baseURL = 'https://dhlottery.co.kr/gameResult.do?method=byWin&drwNo=' if current is None: current = datetime.datetime.now() weeks = str(getWeeks(current.year, current.month, current.day)) url = baseURL + weeks data = requests.get(url, headers=headers) soup = BeautifulSoup(data.text, 'html.parser') numberData = soup.find('meta', id='desc')['content'] boolean, result = parse(numberData, weeks) return boolean, result def replay(something, current, sleep, bot, chatid): while True: boolean, result = something(current) if boolean: bot.sendMessage(chatid, text=result) break waitingMsg = result + '\n' + str(int(sleep/60)) + '분 후에 다시 확인합니다.' bot.sendMessage(chatid, text=waitingMsg) time.sleep(sleep)
한 사이클이 완료되었으니, 매주 실행하도록 지정한다. [스케쥴링] 특정 시간에 실행하기 - 휴장일 커버에서 썼던 방법을 수정했다.
실행 기준 일자를 확인하고,
토요일 추첨전인 경우 추첨시간(20시 47분)까지 sleep,
추첨후인 경우 해당 일자 작업을 실행 후 sleep,
토요일 외의 일자인 경우 다음 토요일 20시 47분까지 sleep
def runEvery(days, times, replay, something, sleep, bot, chatid, current=None): if current is None: current = datetime.datetime.now() gameTime = datetime.datetime(current.year, current.month, current.day, times[0], times[1]) if current.weekday() in days: # 토요일인 경우 if current < gameTime: # 추첨전인 경우 sleepTime = (gameTime - current).total_seconds() print("다음 실행시각:", gameTime, sleepTime) time.sleep(sleepTime) else: # 추첨이 끝난 경우 print("전송합니다.") replay(something, current, sleep, bot, chatid) # 실행 pass # 나머지 시간에 실행하도록 리턴 # 날짜 넘기기 plusDay = 5 - current.weekday() if plusDay <= 0: # 토/일요일인 경우 plusDay += 7 # 다음주로 넘기기 nextTime = gameTime + datetime.timedelta(days=plusDay) sleepTime = (nextTime - current).total_seconds() print("다음 실행시각:", nextTime, sleepTime) time.sleep(sleepTime) while True: print(runEvery([5], [20, 47], replay, getData, 300, BOTobject, chatID))
이제 백그라운드에서 돌리고 로그를 저장한다. (봇 항상 켜두기)
# nohup python -u scripts.py > logfile.log 2>&1 &
로그를 확인해보니 정상적으로 작동하고 있다.
''' nohup: ignoring input 다음 실행시각: 2021-01-09 20:47:00 451427.048589 '''
'Python > 웹스크래핑.데이터수집' 카테고리의 다른 글
[데이터수집] 한국부동산원 청약홈/청약Home 분양정보 (2) (0) 2020.12.29 [데이터수집] 한국부동산원 청약홈/청약Home 분양정보 (1) (0) 2020.12.27