Python
[Python] 로또(동행복권) 정보 크롤러_2단계(회차별 1등 당첨번호 크롤링&DB 저장)
깜짱 ・ 2018. 12. 4. 17:00
URL 복사 이웃추가
본문 기타 기능
신고하기
Github 링크 : https://github.com/kamzzang/WebCrawler
이제 본격적으로 회차별 로또 당첨번호, 당첨자 수, 당첨 금액을 크롤링해서 받아보고자 한다.
"저 당첨자 수에 내가 있으면 얼마나 좋을까"라는 생각만 해도 설레는 마음으로 시작해보자.
1
최신 회차 확인하기
파이썬 코드를 실행시키는 시점에서의 제일 최신 회차가 몇 회인지 크롤링을 통해서 받아온다.
아래 링크의 메인에 최신 회차 정보가 표시된다.
* 먼저 크롤링을 하기 전에는 해당 사이트의 "robots.txt"를 확인해야 한다. 이것은 웹사이트에 크롤러 같은 로봇들의 접근을 제어하기 위한 규약이다. 메인 주소 뒤에 /robots.txt로 이동하면(www.dhlottery.co.kr/robots.txt) 나오는데, 로또 사이트에는 이 규약 자체가 없다. 크롤링에 제약이 없다는 뜻이기 때문에 걱정 없이 데이터를 가져올 수 있다.
나중에 다른 사이트를 크롤링할때 규약에 대해서 자세히 이야기해보도록 하겠다.
오른쪽 마우스를 눌러서 "페이지 소스 보기"를 클릭하면,
아래와 같이 보기도 어려운 것들이 새 탭에 뜨는데 내용 중에 로또의 최신 회차와 결과가 나오는 부분이 있는데 이것을 크롤링으로 받아올 것이다.
<meta id="desc" name="description" content="동행복권 835회 당첨번호 9,10,13,28,38,45+35. 1등 총 15명, 1인당 당첨금액 1,233,681,125원.">
에서 835만 받아오면 되므로, 아래와 같은 코드로 해당 부분만 뽑아서 return하도록 만든다.
특정한 회차의 결과를 받기 위해서 최신 회차를 받는 것인데, 회차를 integer로 해서 숫자만 바뀌면 해당 결과를 받아올 수 있도록 만들 예정이다.
import pandas as pdimport requestsfrom bs4 import BeautifulSoup# 마지막 회차 확인 주소main_url = "https://www.dhlottery.co.kr/gameResult.do?method=byWin"# 마지막 회차 확인 함수def GetLast(): resp = requests.get(main_url) soup = BeautifulSoup(resp.text, "lxml") result = str(soup.find("meta", {"id" : "desc", "name" : "description"})['content']) # meta 태그에서 id 속성이 desc이고 name 속성이 description인 태그를 찾아 content를 string으로 result에 저장 s_idx = result.find(" ") # 1. 회차 앞에 공란이 있고 e_idx = result.find("회") # 2. 회차 다음에 '회'가 나오기 때문에 return int(result[s_idx + 1 : e_idx]) # 3. 공란 다음부터 '회'이전까지가 마지막 회차이며 이것을 integer로 변환하여 리턴한다.last= GetLast()print(last)
실행한 결과
835
가 나온다. (최신 회차가 2018년 12월 1일 835회다.)
2
최신 회차의 당첨 정보 크롤링
최신 회차가 835회라는 것을 알았으니 해당 회차의 당첨번호와 당첨자 수, 당첨 금액을 크롤링해보겠다.
1의 최신 회차를 받았던 주소에서 아래 캡쳐처럼 지난 회차 당첨번호 바로가기에서 회차를 선택하고 조회를 누르면 각 회차별로 해당 URL이 다른 것을 알 수 있다.
https://www.dhlottery.co.kr/gameResult.do?method=byWin&drwNo=835
https://www.dhlottery.co.kr/gameResult.do?method=byWin&drwNo=834
이 점을 이용하면 당첨 정보를 받아오는 크롤러 함수에 회차가 전달되게 해서 특정 회차별 정보를 받을 수 있게 할 수 있다.
import pandas as pdimport requestsfrom bs4 import BeautifulSoup# 마지막 회차 확인 주소main_url = "https://www.dhlottery.co.kr/gameResult.do?method=byWin"# 회차별 당첨 정보 주소basic_url = "https://www.dhlottery.co.kr/gameResult.do?method=byWin&drwNo="# 마지막 회차 확인 함수def GetLast(): resp = requests.get(main_url) soup = BeautifulSoup(resp.text, "lxml") result = str(soup.find("meta", {"id" : "desc", "name" : "description"})['content']) # meta 태그에서 id 속성이 desc이고 name 속성이 description인 태그를 찾아 content를 string으로 result에 저장 s_idx = result.find(" ") # 1. 회차 앞에 공란이 있고 e_idx = result.find("회") # 2. 회차 다음에 '회'가 나오기 때문에 return int(result[s_idx + 1 : e_idx]) # 3. 공란 다음부터 '회'이전까지가 마지막 회차이며 이것을 integer로 변환하여 리턴한다.# 입력한 회차 정보 크롤링 함수def Crawler(count): crawler_url = basic_url + str(count) resp = requests.get(crawler_url) soup = BeautifulSoup(resp.text, "lxml") result = str(soup.find("meta", {"id": "desc", "name": "description"})['content']) # result : 동행복권 835회 당첨번호 9,10,13,28,38,45+35. 1등 총 15명, 1인당 당첨금액 1,233,681,125원. s_idx = result.find("당첨번호") s_idx = result.find(" ", s_idx) + 1 # find() 함수 : string.find(search, start, end) e_idx = result.find(".", s_idx) numbers = result[s_idx:e_idx] s_idx = result.find("총") s_idx = result.find(" ", s_idx) + 1 e_idx = result.find("명", s_idx) persons = result[s_idx:e_idx] s_idx = result.find("당첨금액") s_idx = result.find(" ", s_idx) + 1 e_idx = result.find("원", s_idx) price = result[s_idx:e_idx] info = {} # 당첨정보 저장 Dictionary info["회차"] = count info["당첨번호"] = numbers info["당첨자수"] = persons info["당첨금액"] = price lotto_list.append(info) # 결과 저장 리스트에 추가lotto_list = [] # 웹 크롤링 한 결과를 저장할 리스트last = GetLast() # 최신 회차 받기Crawler(last) # 최신 회차 결과 크롤링print(lotto_list)
실행 결과
[{'회차': 835, '당첨번호': '9,10,13,28,38,45+35', '당첨자수': '15', '당첨금액': '1,233,681,125'}]
지난 주에 15분이 인생역전하셨구나... 축하드려요~~ 유후~~
3
여러 회차의 당첨 정보 크롤링 후
DB 저장하기
이제 한꺼번에 여러 회차의 당첨 정보를 받아와서 DB에 저장을 해보려고 한다.
여러 회차를 받는 부분은 위의 코드에서 Crawler 함수를 시작 회차와 끝 회차를 인수로 받게 하고 for 반복문을 실행하게 하면 된다.
# 입력한 여러 회차 정보 크롤링 함수def Crawler(s_count, e_count): for i in range(s_count , e_count + 1): crawler_url = basic_url + str(i) resp = requests.get(crawler_url) soup = BeautifulSoup(resp.text, "lxml") result = str(soup.find("meta", {"id": "desc", "name": "description"})['content']) # result : 동행복권 835회 당첨번호 9,10,13,28,38,45+35. 1등 총 15명, 1인당 당첨금액 1,233,681,125원. s_idx = result.find("당첨번호") s_idx = result.find(" ", s_idx) + 1 # find() 함수 : string.find(search, start, end) e_idx = result.find(".", s_idx) numbers = result[s_idx:e_idx] s_idx = result.find("총") s_idx = result.find(" ", s_idx) + 1 e_idx = result.find("명", s_idx) persons = result[s_idx:e_idx] s_idx = result.find("당첨금액") s_idx = result.find(" ", s_idx) + 1 e_idx = result.find("원", s_idx) price = result[s_idx:e_idx] info = {} # 당첨정보 저장 Dictionary info["회차"] = i info["당첨번호"] = numbers info["당첨자수"] = persons info["당첨금액"] = price lotto_list.append(info) # 결과 저장 리스트에 추가
그리고, DB 저장을 위해서 "Lotto.db"에 테이블을 만들어준다.
테이블 생성하기 - 필드 추가로 아래와 같이 필드를 생성하고, OK클릭
완성이다!
최신 회차부터 총 10회의 당첨 결과를 저장하도록 코드를 수정했다.
1회차 부터 최신회차까지 모두 받아서 DB에 저장하고 나면, "이것만 있으면 나도 부자가 곧 될거 같은 든든한 느낌이 든다"
나만 그런가...
import pandas as pdimport sqlite3import requestsfrom bs4 import BeautifulSoup# 마지막 회차 확인 주소main_url = "https://www.dhlottery.co.kr/gameResult.do?method=byWin"# 회차별 당첨 정보 주소basic_url = "https://www.dhlottery.co.kr/gameResult.do?method=byWin&drwNo="# 마지막 회차 확인 함수def GetLast(): resp = requests.get(main_url) soup = BeautifulSoup(resp.text, "lxml") result = str(soup.find("meta", {"id" : "desc", "name" : "description"})['content']) # meta 태그에서 id 속성이 desc이고 name 속성이 description인 태그를 찾아 content를 string으로 result에 저장 s_idx = result.find(" ") # 1. 회차 앞에 공란이 있고 e_idx = result.find("회") # 2. 회차 다음에 '회'가 나오기 때문에 return int(result[s_idx + 1 : e_idx]) # 3. 공란 다음부터 '회'이전까지가 마지막 회차이며 이것을 integer로 변환하여 리턴한다.# 입력한 여러 회차 정보 크롤링 함수def Crawler(s_count, e_count): for i in range(s_count , e_count + 1): print(str(i) + "회차 크롤링") crawler_url = basic_url + str(i) resp = requests.get(crawler_url) soup = BeautifulSoup(resp.text, "lxml") result = str(soup.find("meta", {"id": "desc", "name": "description"})['content']) # result : 동행복권 835회 당첨번호 9,10,13,28,38,45+35. 1등 총 15명, 1인당 당첨금액 1,233,681,125원. s_idx = result.find("당첨번호") s_idx = result.find(" ", s_idx) + 1 # find() 함수 : string.find(search, start, end) e_idx = result.find(".", s_idx) numbers = result[s_idx:e_idx] s_idx = result.find("총") s_idx = result.find(" ", s_idx) + 1 e_idx = result.find("명", s_idx) persons = result[s_idx:e_idx] s_idx = result.find("당첨금액") s_idx = result.find(" ", s_idx) + 1 e_idx = result.find("원", s_idx) price = result[s_idx:e_idx] info = {} # 당첨정보 저장 Dictionary info["회차"] = i info["당첨번호"] = numbers info["당첨자수"] = persons info["당첨금액"] = price lotto_list.append(info) # 결과 저장 리스트에 추가def DatatoDB(): print("DATA 저장") df = pd.DataFrame() count = [] num1 = [] num2 = [] num3 = [] num4 = [] num5 = [] num6 = [] num7 = [] persons = [] price = [] con = sqlite3.connect("Lotto.db") for i in lotto_list: count = i["회차"] numbers = i["당첨번호"] persons = i["당첨자수"] price = i["당첨금액"] numberlist = str(numbers).split(",") sql = "INSERT INTO `회차별_당첨정보`(`회차`, `1`, `2`, `3`, `4`, `5`, `6`, `7`, `당첨자수`, `당첨금액`) " \ "VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" data = (count, int(numberlist[0]), int(numberlist[1]), int(numberlist[2]), int(numberlist[3]), int(numberlist[4]), int(numberlist[5].split("+")[0]), int(numberlist[5].split("+")[1]), int(persons), str(price)) cur = con.cursor() cur.execute(sql,data) con.commit() # 중복데이터 제거 sql = "DELETE FROM `회차별_당첨정보` WHERE rowid NOT IN (SELECT Max(rowid) FROM `회차별_당첨정보` GROUP BY 회차 order by 회차)" cur.execute(sql) con.commit() con.close()lotto_list = [] # 웹 크롤링 한 결과를 저장할 리스트last = GetLast() # 최신 회차 받기Crawler(last-10,last) # 최신 회차 이전 10회의 결과 크롤링DatatoDB() # 저장된 모든 정보를 DB에 저장
<결과>
12월 3일부로 로또가 나눔로또에서 동행복권으로 사업자 변경과 더불어 명칭, 홈페이지까지 변경이 되어서 부랴부랴 준비했던 캡쳐 등을 수정했다.
이런 경우 코드는 URL부분만 바꿔주고, 혹시나 크롤링하는 부분에 태크 등이 변경되었는지만 확인해서 수정해주면 된다.
지금까지 2회에 걸쳐서 파이썬으로 CSV 파일의 내용을 불러와서 dataframe 형태로 변경하여 DB에 저장했고, 크롤링한 데이터를 DB에 저장하는 것까지 해봤다.
이것을 기본으로 하여 다양한 정보들을 수집/저장을 할 수 있고, 자동화까지 가능하니 차근차근해서 보다 스마트한 삶을 누려보자~
댓글39 이 글에 댓글 단 블로거 열고 닫기
인쇄