레이블이 로또인 게시물을 표시합니다. 모든 게시물 표시
레이블이 로또인 게시물을 표시합니다. 모든 게시물 표시

2011년 3월 28일 월요일

홈페이지에 나눔로또 위젯을 달아봅시다

예전에 만들어 놓은 나눔로또 Web API를 사용해서 홈페이지나 블로그에 간단하게 추가할 수 있는 나눔로또 당첨 번호 위젯을 만들어 보았습니다. Google App Engine (Python)에 대해 공부해볼 겸해서 만들었던 것이라 그다지 큰 쓰임새가 없었는데 이렇게라도 소개를 하면 그나마 좀 쓰이지 않을까 해서 글로 남겨봅니다. ;-)

몇 줄 안 되는 HTML + JavaScript 코드이므로 적당한 곳에 그대로 아래 코드를 추가하면 됩니다. (Blogger에서는 대시보드 -> 꾸미기 -> 페이지 구성요소 -> 가젯 추가 -> HTML/JavaScript 선택한 다음 아래 코드를 본문에 붙여넣기 하면 됩니다.) 단, 웹이 제 전문 분야가 아니라서 별로 예쁘지는 않습니다. 그저 그럭저럭 잘 동작한다는 데에 의미를 두고 싶습니다. :-( 그러니 화면에 보여지는 모양을 변경하고 싶거나 다르게 동작하길 원한다면 loadLotto 함수의 내용을 적절히 수정하면 되겠습니다.

<div id="lottoDiv">loading...</div>
<script type="text/javascript">
function loadLotto(a) {
  lotpane = document.getElementById('lottoDiv');
  lotpane.innerHTML = '제 <span style="color: green;"><b>' +
      a.gno + '</b></span>회 (' + a.gdate + ')<br /><b><span style="color: red;">' + 
      a.nums + '</span> / <span style="color: blue;">' + a.bnum + '</span></b>';
}
</script>
<script type="text/javascript" src="http://lotto.kaisyu.com/api?method=get&callback=loadLotto">
</script>

소스 내용이 간단하므로 이해하는 데 큰 어려움은 없겠지만 간단히 설명을 하자면 크게 세 부분으로 나눌 수 있습니다.

  1. div 태그: 나눔로또 번호가 표시될 위치에 id가 lottoDiv인 div 태그를 하나 만들어 둡니다.
  2. 첫 번째 script 태그: Callback으로 호출될 JavaScript 함수 loadLotto를 만듭니다. 이 함수는 인자로 넘어온 a 객체에서 필요한 정보를 가져다 화면에 보여줄 HTML 코드를 생성한 다음 lottoDivinnerHTML 값으로 지정해줍니다. (a 객체의 구성에 대한 상세한 내용은 나눔로또 Web API를 참고해주세요.)
  3. 두 번째 script 태그: 이제 준비가 되었으므로 Lotto-K Web API를 호출하는 URL을 script 태그의 src 속성에 추가합니다. 이 때 첫 번째 script 태그에서 만들어둔 함수의 이름(loadLotto)을 callback 파라미터에 넘겨줍니다.

    브라우저에서 직접 이 URL을 입력해보면 그 결과가 아래와 같습니다. JSON 형식으로 된 나눔로또 당첨 번호 오브젝트를 파라미터로 가지는 loadLotto 함수 호출 형태라는 것을 한 눈에 알 수 있습니다.
    loadLotto({"bnum": 35, "gno": 434, "gdate": "2011-03-26", "nums": [3, 13, 20, 24, 33, 37]})
    그러므로 이 내용을 script 태그에 src 속성으로 지정하여 실행하면 첫 번째 script 태그에서 정의한 loadLotto 함수에 나눔로또 당첨 번호 오브젝트가 전달되는 것이죠.

실제로 페이지 내에 추가해서 실행한 결과는 아래와 같습니다.

loading...

위에서 소개한 내용 외에 나눔로또 당첨 여부를 확인할 수 있는 버튼 위젯에 대한 예제도 있으므로 관심 있는 분들은 여기를 따라가보세요.

그리고, 혹시 사용하면서 궁금한 점이 있거나 API 기능 추가에 대해 건의하고 싶은 내용이 있으면 언제든 댓글 남겨주세요. 능력이 되는 범위 내에서 천천히 수정해보겠습니다. :)

2010년 9월 15일 수요일

나눔로또 정보 확인 메신저 봇(bot)

예전에 goo.gl 관련 자료를 찾다가 우연히 발견한 소스를 보고, Google App Engine을 사용하면 Google Talk(XMPP) 호환 메신저 봇(bot)을 간편하게 만들 수 있다는 걸 알게 됐습니다. 사실, Google App Engine의 sample project 모음이나 공식 개발 문서에 설명이 잘 되어 있더군요. 주의 깊게 살펴보지 않아서 몰랐던 것일 뿐... ^^;

그래서, Google App Engine XMPP 서비스에 대해 공부도 해볼 겸 나눔로또 정보를 확인할 수 있는 간단한 메신저 봇을 만들어 보았습니다. Sample project 모음에 예제 소스가 잘 구현되어 있고 관련 문서도 잘 정리되어 있어서 구현 자체는 그다지 어렵지 않았습니다. 로또 관련 라이브러리도 예전에 만들어둔 것을 그대로 가져다 사용했기 때문에 금방 만들 수 있었지요.

테스트 해보실 분들은 아래 주소를 Google Talk이나 XMPP 호환 메신저에 친구로 등록하고 간단한 명령을 입력해보세요.
Bot ID: lotto-k2@appspot.com

도움말을 제외하고 현재 사용할 수 있는 명령은 세 가지입니다.

1. help
도움말을 보여 줍니다.
me는 명령을 입력하는 사람이고, lotto-k는 봇입니다.
me:
help

lotto-k:
Korean Lotto 645 Bot.
=====================
- get or get [lotto game no. or 0]
ex1) get
ex2) get 0
ex3) get 375
- try [lotto game no. or 0] [your numbers]
ex1) try 0 4,8,19,25,27,42
ex2) try 375 4,8,19,25,27,42
- take or take [1~5]
ex1) take
ex2) take 5
-------
for more details: http://lotto.kaisyu.com

2. get [로또 회차]
주어진 로또 회차에 대한 정보를 보여 줍니다.
봇 출력 결과에 대해 간단히 설명하면,
1) game no. - 로또 회차
2) date - 로또 추첨일
3) winning numbers - 로또 당첨 번호
명령으로 'get'만 입력하거나 'get 0'라고 입력하면 가장 최근의 로또 당첨 정보를 알려 줍니다.
me:
get 375

lotto-k:
game no.: 375
date: 2010-02-06
winning numbers: 4, 8, 19, 25, 27, 45 / (7)

3. try [로또 회차] [비교할 번호]
주어진 로또 회차와 번호들을 비교하여 당첨 여부에 대한 결과를 알려 줍니다.
봇 출력 결과에 대해 간단히 설명하면,
1) rank - 로또 당첨 등수
2) game no. - 로또 회차
3) date - 로또 추첨일
4) trying numbers - 내 번호
5) winning numbers - 로또 당첨 번호
6) matched number(s) - 일치한 번호
역시 'get' 명령과 유사하게 로또 회차에 '0'을 주면 가장 최근의 로또 당첨 번호와 비교하게 됩니다. 그러나 생략은 불가능합니다.
me:
try 375 4,8,19,25,27,42

lotto-k:
rank: 3
game no.: 375
date: 2010-02-06
winning numbers: 4, 8, 19, 25, 27, 45 / (7)
trying numbers: 4, 8, 19, 25, 27, 42
matched number(s): 4, 8, 19, 25, 27

4. take [랜덤 생성할 회수]
주어진 회수만큼 로또 예상 번호를 랜덤으로 생성해 줍니다.
메신저 봇이 폭주(?)하는 것을 막기 위해 랜덤 생성 회수는 최대 5까지만 지정할 수 있습니다. 더 큰 수를 주더라도 5로 변경됩니다.
me:
take 3

lotto-k:
11, 19, 23, 33, 38, 43
1, 5, 8, 21, 28, 45
12, 23, 25, 26, 28, 40

2010년 7월 12일 월요일

Emacs 나눔로또 API & Module

아래 내용은 초기 버전에 대한 것으로 업데이트된 최신 내용은 프로젝트 위키 페이지에서 확인하실 수 있습니다. -- 2011-04-19
LINK: lotto-check-el/wiki/EmacsLottoApi



로또 이야기가 계속 이어지네요. 이 정도 정성이면 로또 1 등 내려주실 법도 한데, 5 등 한번 당첨되기도 쉽지 않으니 하늘이 무심(?)하십니다.

이번에는 Emacs에서 사용할 수 있는, 나눔로또 정보 및 당첨 여부 확인 모듈을 만들었습니다. Emacs Lisp 공부도 좀 하고 앞서 만들었던 로또 당첨 정보 Web API도 써먹어 볼 겸 만들어 본 것입니다. 그리고, 이번에 만든 것은 무려 소스까지도 공개합니다. 부끄러운 소스지만, 어쨌거나 GPL version 3를 채택해서 공개해봅니다.

공개된 소스의 저장소 URL은 다음과 같습니다.
LINK: http://bitbucket.org/kaisyu/lotto-check/
LINK: https://code.google.com/p/lotto-check-el/
LINK: https://github.com/kaisyu/lotto-check
LINK: https://gitlab.com/kaisyu/lotto-check

1. 소개 및 특징

로또 당첨 번호와 내가 구매한 로또의 당첨 여부를 Emacs에서 간편하게 확인할 수 있는 모듈입니다. 이 모듈은 다음과 같은 특징을 가지고 있습니다.

1) 인터넷을 통해 로또 정보를 수집하는 방법을 하나 이상 지원합니다.
로또 당첨 번호 정보는 인터넷을 통해 수집하게 되는데, 기본으로 @Lotto_K 계정에 게시되는 것과 동일한 정보를 사용하는 lotto.kaisyu.com 사이트의 Web API를 사용합니다. 그리고, 혹시라도 이 사이트에 문제가 생겼을 경우를 대비해 네이버, 다음, 나눔로또 공식 홈페이지 등의 대체 방법도 제공합니다.

2) Hashtable을 활용한 local cache를 유지합니다.
이로 인해 한번 가져온 로또 정보는 추가 인터넷 연결 없이 매우 빠르게 그 결과를 확인할 수 있습니다. 이 local cache는 lotto-check 모듈이 로드되거나 평가될 때 파일로부터 자동으로 읽혀져 초기화 되고, Emacs가 종료될 때 자동으로 파일에 저장됩니다.

3) 간단하게 즉시 사용할 수 있는 interactive 함수를 제공합니다.
M-x 함수명 형식으로 사용할 수 있는 함수들을 제공합니다. 로또 당첨 번호 정보를 보여주고, 사용자가 제공한 번호의 당첨 여부도 확인해주는 함수들로, 그 결과가 새로운 전용 buffer에 출력되거나 message 형태로 보여집니다. 자세한 것은 아래에 다시 소개하겠습니다.

4) 다른 모듈에서 간편하게 사용할 수 있는 API 함수를 제공합니다.
위에서 소개한 interactive 함수들과 동일한 역할을 하는 API 함수가 존재하는데, interactive 함수들과 다른 점은 반환값이 lisp object 형태로 되어 있어 재가공하거나 변환하여 사용하기 편리하다는 점입니다.


2. 설치 및 설정

1) 설치
다운로드한 소스를 load path에 추가해줍니다.
(add-to-list 'load-path "[lotto-check 모듈이 있는 경로]")
(require 'lotto-check)

2) 설정
Emacs의 Customize 기능(M-x customize)을 사용해서 Applications 그룹 아래의 Lotto 그룹으로 가면 간편하게 설정할 수 있는 UI가 제공되지만, 아래와 같이 직접 startup script 파일에 설정을 추가하는 것도 가능합니다.
;; 로또 당첨 정보를 인터넷으로부터 수집하는 함수를 지정합니다.
;; 기본값은 lotto-retrieve-numbers-from-lotto-k 함수이며,
;; 네이버, 다음, 나눔로또 공식 홈페이지, 사용자 정의 방법 등을 제공합니다.
;; 네이버: lotto-retrieve-numbers-from-naver
;; 다음: lotto-retrieve-numbers-from-daum
;; 나눔로또 공식 홈페이지: lotto-retrieve-numbers-from-645lotto
;; 사용자 정의 함수: lotto-info-retrieve-func-custom
;; * 사용자 정의 함수 방식을 사용할 경우 lotto-info-retrieve-func-custom 변수에
;;   사용자 정의 함수 이름을 지정합니다.
;;   예) (setq lotto-info-retrieve-func-custom 'my-retrieve-func-1)
(setq lotto-info-retrieve-func 'lotto-retrieve-numbers-from-lotto-k)
;; 로또 당첨 정보를 저장할 파일을 지정합니다.
(setq lotto-database-file "~/.lotto-database")
;; interactive function 실행 시 결과를 별도의 buffer에 보여주도록 설정합니다.
(setq lotto-use-buffer-for-message t)


3. 사용

1) interactive 함수 사용하기
  • M-x lotto-retrieve-numbers-i특정 회차의 당첨 번호 정보를 보여줍니다.
    실행하면 mini-buffer에 game no: 프롬프트가 뜨는데, 가져올 로또 회차 번호를 입력합니다.
    예) game no: 397
  • M-x lotto-check-numbers-list-i특정 회차에 사용자가 지정한 번호의 당첨 여부를 확인하여 결과를 보여줍니다.
    실행하면 minu-buffer에 game no: 프롬프트와 your numbers: 프롬프트가 뜨는데, 각각 비교할 로또 회차 번호와 확인할 번호 list를 입력합니다.
    확인할 번호 list 형식은 일반적인 lisp object와 동일합니다.
    예) your numbers: ((1 14 16 25 33 42) (2 10 17 26 34 43))
  • M-x lotto-save-db-to-file-ilocal cache에 저장된 로또 당첨 번호 정보를 파일에 저장합니다. 사용자가 수동으로 저장하지 않아도 Emacs 종료 시 자동으로 저장됩니다.
  • M-x lotto-load-db-to-file-i파일에 저장된 로또 당첨 번호 정보를 불러옵니다. 사용자가 수동으로 불러오지 않아도 lotto-check 모듈을 불러올 때 자동으로 local cache도 함께 불러옵니다.
[lotto-check 모듈 실행 결과]

2) API 함수 사용하기
(lotto-retrieve-numbers GNO)

로또 당첨 번호를 반환합니다.
GNO: 가져올 로또 회차 번호
반환값: ((당첨_번호_list) 보너스_번호)

예) (lotto-retrieve-numbers 395)
=> ((11 15 20 26 31 35) 7)
(lotto-check-numbers-list GNO MY-NUM-LIST)

주어진 번호의 당첨 여부를 반환합니다.
GNO: 비교할 로또 회차 번호
MY-NUM-LIST: 확인할 번호들의 list
반환값: ((등급 (일치한_번호_list)) ...)

예) (lotto-check-numbers-list 395 '((1 2 3 4 5 6) (11 15 20 28 32 36)))
=> ((0 nil) (5 (11 15 20)))

2010년 7월 5일 월요일

간단한 나눔로또 Web API

근래에 로또와 관련된 글을 좀 자주 쓰는 듯 하군요. ;-)

앞서 Google App Engine 위에 만들었던 로또 정보 제공 사이트의 내용을 조금 수정해서 원하는 로또 정보를 제공 받을 수 있는 Web 용 API를 만들어보았습니다.

사용 방법은 간단합니다.

기본 URL

나눔로또 Web API 기본 URL은 아래와 같습니다.

http://lotto.kaisyu.com/api

파라미터

method = get | check

실행할 동작을 결정합니다. 아래 두 가지 중 하나를 선택할 수 있으며, 생략은 불가능합니다.

  • get: 로또 정보 반환
  • check: 로또 번호 당첨 여부 확인

gno = 0 ~ 최근 로또 회차 번호

로또 회차 번호입니다. 생략하거나 0 이하의 값이면 DB에 저장된 회차 번호 중 가장 최근의 번호가 사용됩니다.

type = json | python | emacs

반환되는 값의 형식을 지정합니다. 생략하면 json 형식이 기본으로 사용됩니다.

  • json: JSON 형식
  • python: Python dict 형식
  • emacs: Emacs lisp를 포함한 일반적인 Lisp object 형식

callback = (javascript_function_name)

method 파라미터의 값이 json일 때만 사용되며, 지정된 JavaScript 함수에 결과값을 인자로 주어 호출하는 코드를 반환합니다.

numlist = [[n,...],[n,...],...]

당첨 여부를 확인할 번호 목록입니다. method가 check로 지정되었을 때만 사용되며, 리스트의 리스트 형식입니다.

반환값

get

일반적으로 볼 수 있는 사전 형식을 사용합니다. (각 아이템의 순서는 일정하지 않음)

  • gno: 로또 회차 번호
  • gdate: 추첨일
  • nums: 당첨 번호 목록
  • bnum: 보너스 당첨 번호

예를 들어보면,

202회차, 2006년 10월 14일 추첨, 보너스 번호는 17, JSON 형식

{"bnum": 17, "gno": 202, "gdate": "2006-10-14", "nums": [12, 14, 27, 33, 39, 44]}

301회차, 2008년 9월 6일 추첨, 보너스 번호는 26, Python 형식

{'bnum': 26, 'gno': 301, 'gdate': '2008-09-06', 'nums': [7, 11, 13, 33, 37, 43]}

396회차, 2010년 7월 3일 추첨, 보너스 번호는 30, Emacs Lisp object 형식

((bnum . 30) (gno . 396) (gdate . "2010-07-03") (nums . (18 20 31 34 40 45)))

check

[당첨 등수, 일치 번호 목록] 형식의 리스트를 반환합니다. (리스트의 리스트) 이때, 당첨 등수값이 0이면 꽝!!을 의미합니다.

예를 들어보면,

1 게임을 확인했고, 5 등 당첨되었으며, 일치한 번호는 27, 33, 44, JSON 형식

[[5, [27, 33, 44]]]

2 게임을 확인했고, 하나는 꽝, 나머지 하나는 5 등 당첨, Python 자료 구조 형식

[(0, [12]), (4, [14, 27, 33, 44])]

3 게임을 확인했고, 하나는 꽝, 하나는 5 등 당첨, 나머지 하나는 대망의 1 등 당첨, Emacs Lisp object 형식

((0 (12)) (4 (14 27 33 44)) (1 (12 14 27 33 39 44)))

예제

JavaScript Callback 함수를 활용한 예제

JavaScript Callback 함수를 활용한 예제는 별도의 페이지에서 제공하므로 아래 링크를 따라가세요.

기타 URL 예제들

get

check

2010년 5월 13일 목요일

나눔로또 유감

얼마 전에 나눔로또 공식 홈페이지에서 로또 당첨 번호 정보를 가져오는 방법에 대해 글을 쓴 적이 있습니다. Google App Engine (Python)을 사용해서 간단한 데모 사이트도 만들었는데, 요 며칠 사이에 데모 사이트가 제대로 동작하지 않는 겁니다. 무슨 일일까 궁금해 에러 로그를 살펴보고 몇 가지 간단한 테스트를 해본 결과, 나눔 로또 공식 홈페이지에서 Google App Engine 사이트로부터 오는 트래픽을 차단했다는 사실을 알게 됐습니다. (다른 곳도 차단했는지 어떤지는 잘 모르겠지만, 제가 확인해본 범위 내에서는 아직 없습니다.)

흠... 뭐랄까요, 기분이 좀 묘합니다.

설마 제가 쓴 글 때문에 Google App Engine으로부터 엄청난 트래픽이 발생한 걸까요? 아마 그렇지는 않을 겁니다. 제 블로그는 변방에 있는 잘 알려지지 않은 곳이고, 최근 트래픽 분석 로그를 확인해봐도 제가 쓴 글에 대한 조회수가 얼마 되지 않습니다. 결국 그냥 자기네 사이트의 정보를 활용하는 것이 아니꼬왔기 때문이 아닐까요? (저는 오히려 나눔로또 공식 홈페이지 운영팀에서 제가 쓴 글을 어떻게 알고 찾아와서 봤을까 하는 점이 더 궁금합니다.) 차라리, Google App Engine에서 오는 트래픽을 차단한 이유가 실제로는 전혀 다른 데에 있고 우연히 제가 글을 쓴 시점과 비슷하게 겹친 것을 오해하고 있는 것이라면 정말 다행일 겁니다. 만약 그렇다면 이렇게 말한 것에 대해 제가 나눔로또 공식 홈페이지 운영팀에 사과해야겠지요.

로또 당첨 번호 정보는 비밀 정보가 아닙니다. 로또를 구매하는 고객 입장에서는 당연히 제공 받을 권리가 있는 정보입니다. 로또를 구매하지 않는 사람이라면 이런 정보에는 관심조차 없겠죠. 그렇기 때문에 고객이 더 쉽게 정보를 이용할 수 있도록 노력하는 것이 운영팀의 의무 중 하나가 아닐까 생각합니다. 제가 데모 사이트를 만든 것도 좀더 간편하게 로또 당첨 번호를 확인하고자 하는 필요 때문이었습니다. 그런데, 나눔로또 공식 홈페이지에서는 직접 홈페이지를 방문해서 확인하는 경우를 제외하고는 유료 SMS 알림 서비스라든가 위젯 프로그램 형태로만 제공하고 있더군요. 그러나, 저를 포함해서, 유료 SMS 서비스나 위젯 프로그램 같은 건 사용하고 싶지 않은 사람들이 많을 겁니다. 이미 언급한 적이 있지만, RSS feed 형태로 제공한다든가 Twitter 같은 서비스를 활용해서 공지한다든가 혹은 더 편리하고 고객 친화적인 방법을 고민하는 적극적인 모습이 무척이나 아쉽습니다.

RSS feed를 추가함으로 인해 발생할 트래픽이 두려운 것이라면, private RSS feed 하나 만들고 FeedBurner 같은 서비스로 배포해서 트래픽을 그 쪽으로 전가하면 됩니다. 얼마나 많은 사람이 구독하는지 통계도 볼 수 있으니 오히려 더욱 효과적일 수도 있습니다. Twitter에 게시하는 것은 더 말할 필요도 없겠지요.

Google App Engine으로부터 오는 트래픽을 차단했다고 로또 당첨 번호 정보를 얻어가는 것이 불가능한 게 아니라는 것은 나눔로또 공식 홈페이지 운영팀에서 더 잘 알고 있을 겁니다. 세상도 변하고 IT 환경도 하루가 다르게 변하고 있습니다. 당장의 상황에 대해 눈가리고 아웅 하는 식의 '차단'이라는 소심한 대응 대신 개방적이고 능동적으로 변화하는 모습을 보여줄 수는 없는지요. 저도 분명 로또를 구매하는 고객입니다. 고객의 목소리에 귀를 기울여 주세요.

나눔로또 공식 홈페이지 운영팀의 답변을 기대해봅니다.

2010년 4월 28일 수요일

나눔로또 당첨 정보 가져오기

이 글은 Google App Engine 공부 - 로또 정보 트위터 게시 글의 뒷 이야기 중 하나입니다. 몇 가지 주제들이 있지만, 가장 먼저 다룰 것이 '로또 정보를 어떻게 수집할까' 입니다.

가장 단순한 방법은 로또 추첨 때 지켜보고 있다가 추첨 결과가 나오면 사람이 직접 입력하는 겁니다. 하지만, 이건 좀 비효율적이고, 사람이 하는 일인 만큼 오타, 착시(?) 등으로 인해 잘못된 정보가 게시될 가능성이 있습니다.

결국, 프로그램을 통해 자동화 하는 것이 바람직한 것 같은데, 여기에는 고려할 것이 몇 가지 있습니다.

1. 정보 제공자
매우 당연한 이야기로, 인터넷 상에서 로또 당첨 정보를 제공하는 곳이 있어야 자동화를 구상이라도 해볼 수 있을 겁니다. 어디가 적당할까요? 정말 많은 곳이 있지만, 아무래도 나눔로또 공식 홈페이지 만한 곳이 또 있을까요?

2. 정보 추출 방법
나눔로또 공식 홈페이지를 봅시다. 로또 당첨 정보를 아름답게(?) 보여주고 있습니다.


여기서 우리에게 꼭 필요한 당첨 정보만 추출해야 합니다. 어떻게 할까요? 일단, RSS feed 같은 형식으로 제공해주는 게 있는지 살펴봅니다. 역시나 없습니다.
그런데, 가만히 보면 로또 당첨 정보를 보여주는 부분에서 '이전회차/다음회차'를 부분적으로 갱신해주는 버튼이 있는 걸 알 수 있습니다. Flash로 만들어진 게 아니고 JavaScript를 사용했군요. 이것을 힌트로 HTML 페이지 소스와 JavaScript 소스를 뒤지다 보면 가장 '최근회차'의 당첨 정보를 제공하는 URL이 있다는 것을 알 수 있습니다.
http://www.645lotto.net/resultall/dummy.asp
그리고 그 결과는 이렇게 돌아옵니다.
[{
 GRWNO : "386",
 GRWDate : "2010-04-24",
 FirstBall : "4",
 SecondBall : "7",
 ThirdBall : "10",
 FourthBall : "19",
 FifthBall : "31",
 SixthBall : "40",
 BonusBall : "26"
}]
어디서 많이 본 모양입니다. 그렇습니다. 바로 JSON 형식입니다. 이렇게 되고 보면 저 URL은 비공식적인 로또 정보 제공 API라고 봐도 될 듯합니다.
그럼, 이 정보를 사용해서 간단하게 우리가 필요한 정보만 추출해봅시다. 다음은 Python으로 제가 만든 소스 중 필요한 부분만 추린 간단한 예제입니다. (이 예제에서는 Google App Engine에 포함된 simplejson 라이브러리를 사용하지 않고 간단한 문자열 치환과 eval 함수를 통해 dict 형식으로 가공하는 방법을 썼습니다.)
import httplib
import re

LOTTO645_SITE = "www.645lotto.net"
API_LATEST_URL = "/resultall/dummy.asp"

conn = httplib.HTTPConnection(LOTTO645_SITE)
conn.request("GET", API_LATEST_URL)
res = conn.getresponse()
raw_dat = res.read()
conn.close()

dat = raw_dat.replace('\n', '').replace('\r', '').replace('\t', ' ')
p = re.compile('(\s+)(\w+)(\s+:)')
dic = eval(p.sub('\g<1>"\g<2>"\g<3>', dat))[0]

BALL_NAMES = ['First', 'Second', 'Third', 'Fourth', 'Fifth', 'Sixth']
nums = [dic.get(l + 'Ball') for l in BALL_NAMES]
bnum = int(dic.get('BonusBall'))
lcnt = int(dic.get('GRWNO'))
ldate = dic.get('GRWDate')

print "회차:", lcnt
print "추첨일:", ldate 
print "당첨번호: %s + %d" % (str(nums).replace("'",'')[1:-1], bnum)
출력 결과는 다음과 같습니다.
회차: 386
추첨일: 2010-04-24
당첨번호: 4, 7, 10, 19, 31, 40 + 26

3. 최적화(함께 하는 세상)
자, 이제는 원하는 것을 얻었습니다. 그렇지만, 다 같이 사는 세상입니다. 정보를 얻어 쓰는 주제에 정보 제공자에게 폐를 끼쳐서는 안될 것입니다. 로또 당첨 정보가 필요할 때마다 공식 홈페이지에서 가져오는 것은 아무래도 서버에 부하를 줄 가능성이 있습니다. 처음에는 얼마 안 되겠지만, 차츰 이런 식으로 정보를 가져오는 사람이 늘어나게 되면 서버 관리하는 입장에서는 갑자기 늘어나는 트래픽에 신경이 쓰이게 될 테고 결국 URL을 막아버릴 수도 있을 겁니다.
그러니, 공식 홈페이지에서 정보를 가져오는 빈도를 최소화 해야 합니다. 여러 가지 방법을 생각해볼 수 있겠지만 제가 생각한 방법은, 일 주일에 한 번만 공식 홈페이지에서 정보를 가져와 DB에 저장해두고 필요할 때마다 DB로부터 꺼내어 쓰는 겁니다.

[*] 나눔로또 공식 홈페이지 운영팀에 바랍니다.
어차피 로또 추첨 결과를 널리 알리는 게 목적인 것이라면 단순히 공식 홈페이지에만 게시하고 말 것이 아니라, 'RSS feed 제공'이나 'Twitter 게시' 같은 좀더 적극적인 방법을 통해 공유하는 것이 더 바람직하지 않을까 생각합니다. 고려해주실 거죠?! ;-)


2010년 4월 24일 토요일

Google App Engine 공부 - 로또 정보 트위터 게시

Google App Engine에 대해 공부도 해볼 겸 간단한 웹 애플리케이션 하나 만들어보기로 하고 그 주제로 정한 것이 '로또 정보 트위터 게시 봇'이었습니다. 물론 이미 같은 기능을 하는 애플리케이션들이 여럿 있습니다만, 제 입맛에 딱 맞게 쓰려면 아무래도 직접 만드는 것이 낫겠다 싶었죠. (SKT의 트위팅 SMS 알림 서비스를 통해 트윗 알림을 받게 되면 '80 자'라는 제약 때문에 트윗 내용이 조금만 길어도 잘리게 됩니다. 그래서, SMS 수신된 내용만으로 로또 당첨 번호를 바로 확인할 수 있으려면 최소한의 정보만 표시할 필요가 있었습니다. 얼핏 우스워 보일 수도 있지만, 전 정말 심각했습니다. ㅡㅡ; )

애플리케이션 이름은 Lotto_K. 즉석에서 대강 지은 것이라 그다지 멋진 건 아닙니다. ^^; 아무튼 구경부터 해보시려면 아래 링크로... 아직 별로 볼 건 없습니다.
LINK: http://lotto.kaisyu.com
Twitter: @lotto_k
RSS Feed: Lotto 당첨 정보

하는 일은 크게 세 가지입니다.
  • 나눔로또 공식 홈페이지에서 로또 당첨 번호 정보를 가져온다.
  • 가져온 로또 당첨 번호 정보를 lotto_k 트위터 계정에 게시한다.
  • 매번 페이지 접속할 때마다 새로 임의 생성한 번호 여섯 개를 보여준다.

내부적으로는, 성능 상의 이유로 한번 가져온 로또 당첨 번호 정보를 DB에 저장해둔다든가, 트위터 중복 게시를 막기 위해 마지막으로 게시한 로또 회차 정보를 별도로 유지한다든가 하는 것들이 더 있지만, 겉으로 보이는 부분에서 큰 차이는 없습니다.

만드는 데 사용된 주요 기능(?)들은 다음과 같습니다.

Python 기본 문법 정도만 아는 수준에서 나머지 모든 부분은 인터넷 검색 결과와 기본 제공 문서들을 참고하여 해결하고 작업을 진행했는데 의외로 크게 어렵지 않았습니다. 세상 참 많이 좋아졌다는 말은 괜히 하는 게 아닌가봅니다.

덧. 처음에는 소스를 공개하려고 생각했는데, 약 5 분 정도 소스 코드를 물끄러미 바라본 후 혼잣말로 중얼거리고 말았습니다. '아무래도 당분간은 어려울 것 같군.'



이 글에서 소개한 로또 정보 트위터 게시 앱에 대한 후기도 따로 작성했습니다.

2009년 3월 31일 화요일

[Common Lisp] 로또(Lotto) 번호 생성기

먹고 살기 점점 힘들어져서 이래저래 한숨만 나오는 요즘입니다. 그래서, 혹시나 하는 기대로 로또를 해보기도 하는데, 이건 그때 쓸려고 Common Lisp으로 만든 로또 번호 생성 장난감 코드입니다. 번호를 하나씩 뽑을 때마다 난수 발생 방식으로 수 배열을 섞어줍니다.
(defun random-comp (a b)
(if (= (random 2) 1) t nil))

(defun take-random (lst n mixcnt)
(cond ((null lst) ())
((<= n 0) ())
(t
(let ((nlst
(dotimes (cnt mixcnt lst)
(setq lst (sort lst #'random-comp)))))
(cons (car nlst) (take-random (cdr nlst) (1- n) mixcnt))))))

(defun gen-lotto-seq (mixcnt)
(let ((lst (loop for i from 1 to 45 collect i)))
(take-random lst 6 mixcnt)))

(defun gen-lotto-helper (try mixcnt)
(if (<= try 0)
nil
(cons
(let ((lst (gen-lotto-seq mixcnt)))
(print lst)
(print (apply #'+ lst))
(finish-output)
(sort lst #'<))
(gen-lotto-helper (1- try) mixcnt))))

(defun gen-lotto (try &optional (mixcnt 1000))
(setq *random-state* (make-random-state t))
(gen-lotto-helper try mixcnt))

실행 방법)
(gen-lotto <시도할 게임 수 번호> <하나를 뽑을 때마다 수열을 섞는 회수, 기본값 1000>)

예)
(gen-lotto 5 500) ; 총 5 게임을 시도하고, 각 번호를 뽑을 때마다 500 번씩 섞음
(gen-lotto 3) ; 총 3 게임을 시도하고, 각 번호를 뽑을 때마다 1000 번씩 섞음


아래는 실제로 실행해본 스크린샷입니다.



주의.
이 코드로 인해 발생할 수 있는 정신적 스트레스 및 물질적 궁핍 또는 결여에 대해 저는 어떠한 책임도 지지 않습니다. 단, 이 코드로 인해 발생한 물질적 형태의 이익에 대해 사례를 하시겠다면 마다 하지는 않겠습니다. ;-)