用luasocket讀取雙色球中獎號碼


其實是蠻簡單的一個功能,就是讀取這個頁面:http://61.129.89.226/fcopen/cp_kjgg_dfw.jsp?lottery_type=ssq&lottery_issue=2012138, 把某一個期的中獎號碼抽取出來。

【luarocks安裝library】

首先,如果是想用某個庫,真沒必要自己wget再make, install啥的,太煩。lua社區提供了一個非常好用的工具,用法和apt(advanced package tools)很類似:

apt-cache search xxx
sudo apt-get install xxx

luarocks search xxx
luarocks install xxx

這里需要luasocket,很簡單:

$ luarocks search socket

Search results:
===============

Rockspecs and source rocks:
---------------------------

luasocket
2.0.2-5 (rockspec) - http://luarocks.org/repositories/rocks
2.0.2-5 (src) - http://luarocks.org/repositories/rocks
2.0.2-4 (rockspec) - http://luarocks.org/repositories/rocks
。。。。。。

 

$ luarocks install luasocket
Installing http://luarocks.org/repositories/rocks/luasocket-2.0.2-5.src.rock...
Archive: /tmp/luarocks_luarocks-rock-luasocket-2.0.2-5-2574/luasocket-2.0.2-5.src.rock
。。。。。。
cd src; cp mime.so.1.0.2 /home/baiyanh/.luarocks/lib/luarocks/rocks/luasocket/2.0.2-5/lib/mime/core.so
Updating manifest for /home/baiyanh/.luarocks/lib/luarocks/rocks

 

【讀取頁面】

然后用luasocket發送http get request,來獲取web頁面:

issuenum = arg[1]
if not issuenum then
        error "please provide the lottery issue num!"
end


socket = require "socket"

host = '61.129.89.226'
port = 80
fileformat = '/fcopen/cp_kjgg_dfw.jsp?lottery_type=ssq&lottery_issue=%s'
starting = '開獎結果'
numpattern = '>%d%d<'

function getlotterywinner(issuenum)
        local client = assert(socket.connect(host, port))
        client:send('GET ' .. string.format(fileformat, issuenum)  .. " HTTP/1.0\r\n\r\n")
        local line = client:receive('*l')
        local start = false
        local winner = {}
        while line do
                if line:find(starting) then
                        start = true
                end

                if start then
                        local num = line:match(numpattern)
                        if num then
                                table.insert(winner, num:sub(2, -2))
                        end
                end
                if #winner == 7 then break end
                line = client:receive('*l')
        end
        client:close()
        return winner
end

--http://61.129.89.226/fcopen/cp_kjgg_dfw.jsp?lottery_type=ssq&lottery_issue=2012138
winner = getlotterywinner(issuenum)
for _, v in ipairs(winner) do
        io.write(v .. "  ")
end
io.write("\n")

 

但遺憾的是,上述代碼無法正確輸出結果,事實上,上面“開獎結果”根本無法匹配 - 為什么?

【解決編碼問題】

查看雙色球網頁的source,可以看到這么一行:

<meta http-equiv="Content-Type" content="text/html; charset=gb2312">

該網頁的編碼是gb2312, 而我寫在lua代碼中的“開獎結果”,是和這個lua腳本采用同樣的編碼:utf8,所以無法匹配(他們在內存中的表示方式不同,匹配自然失敗) - 知道了原因就好辦了,只要把他們轉成同樣的編碼即可:

  • 轉碼的方向 - 自然是把“開獎結果”轉成gb2312最省錢
  • 用什么庫 - lua提供了對iconv庫的wrapper,叫lua-iconv

好,下載:

$ luarocks install lua-iconv
Installing http://luarocks.org/repositories/rocks/lua-iconv-7-1.src.rock...
Archive: /tmp/luarocks_luarocks-rock-lua-iconv-7-1-2223/lua-iconv-7-1.src.rock
inflating: lua-iconv-7-1.rockspec
extracting: lua-iconv-7.tar.gz
gcc -O2 -I/usr/include/lua5.1 -c luaiconv.c -o luaiconv.o -I/usr/include
gcc -shared -o iconv.so -L/usr/local/lib luaiconv.o -L/usr/lib
Updating manifest for /home/baiyanh/.luarocks/lib/luarocks/rocks

要熟悉iconv很簡單,因為linux下自帶了一個iconv的命令行工具,查看支持的編碼:

$ iconv --list | grep "^GB"
GB//
GB2312//
GB13000//
GB18030//
GBK//
GB_1988-80//
GB_198880//

修改代碼:

iconv = require "iconv"
cd = iconv.new('gb2312', 'utf8')
starting = cd:iconv('開獎結果')

運行:

$ lua getlotterywinner.lua 2012138
01 07 16 17 19 21 14

 

【玩點酷的】

下面用這個小程序做點有意思的事:查看03年以來藍色球各個數字的概率,或許對指導我買彩票有一定的幫助(籃球中了,最少也有5塊獎金了:))

歷年每年的期數都不相同,但所有的期數都列在這個網頁中了:http://61.129.89.226/fcopen/cp_kjgg_dfw.jsp?lottery_type=ssq&lottery_issue=2012138,所有只要拿到所有的期數,然后調用上面的函數得到中獎號碼,統計一下就ok了:

function allissues()
        local client = assert(socket.connect(host, port))
        client:send('GET ' .. string.format(fileformat, 2012138)  .. " HTTP/1.0\r\n\r\n")
        local line = client:receive('*l')
        local issuepattern = '>%d%d%d%d%d%d%d<'
        return function ()
                while line do
                        local issuenum = line:match(issuepattern)
                        line = client:receive('*l')
                        if issuenum then
                                return issuenum:sub(2, -2)
                        end
                end
                return nil
        end

end

local data = {}
local count = 0
for issuenum in allissues() do
        count = count + 1
        print ("getting " .. issuenum .. "...")
        local winner = getlotterywinner(issuenum)
        local blue = tonumber(winner[7])
        if not data[blue] then
                data[blue] = 0
        end
        data[blue] = data[blue] + 1
end

for k, v in pairs(data) do
        print(string.format("%2d: %3d/%d = %0.4f", k,  v, count, v/count))
end

最終結果:

1: 90/1423 = 0.0632
2: 88/1423 = 0.0618
3: 90/1423 = 0.0632
4: 78/1423 = 0.0548
5: 96/1423 = 0.0675
6: 85/1423 = 0.0597
7: 77/1423 = 0.0541
8: 76/1423 = 0.0534
9: 100/1423 = 0.0703
10: 86/1423 = 0.0604
11: 101/1423 = 0.0710
12: 90/1423 = 0.0632
13: 91/1423 = 0.0639
14: 91/1423 = 0.0639
15: 91/1423 = 0.0639
16: 93/1423 = 0.0654

看來挺平均的,11和9稍微高一點,但也就勝出零點幾個百分點而已。。。

 

【下一步】

做個web service封裝以下這個很hardcode的實現,這樣如果人家網頁的格式變了,或者編碼編了,或者我想換個新的實現,都不會影響最終使用者 - 及時更新web service即可


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM