Python分析一下雙色球,中大獎指日可待!

一、需求簡介
之前偶然見到一位網(wǎng)友提出了關于雙色球數(shù)據(jù)的分析需求,感覺頗有趣味,便著手操作了一番。如下為某雙色球發(fā)布站的頁面,可以看到每期會產生紅/藍兩種顏色的數(shù)字,其中紅球為 33 選 6,藍球為 16 選 1,一共是從 49 個球中選 7 個。假如想對某一色號球下注,比如紅1 球,要先分析一下該球以往的產出情況。
可以從以下 3 個方面來分析,以史明鑒,看看最新一期是否值得選取該球:
1、遺漏情況
統(tǒng)計遺漏 n 期后命中的次數(shù),如上圖:遺漏 1 期后中的次數(shù)有 2 次,遺漏 2 期后中的次數(shù)有 1 次,遺漏 5 期后中的次數(shù)有 2 次,遺漏 7 期后中的次數(shù)有 1 次。
2、連續(xù)重號情況
如圖,連續(xù)重號 3 期的有 1 次。
3、重號前的遺漏情況
如圖,重號前遺漏 2 期的有 1 次。
二、源數(shù)據(jù)
節(jié)選源數(shù)據(jù)如下,數(shù)據(jù)是以 html 表格形式儲存的,<td> 標簽中 class="yl01" 表示未命中,class="chartBall01" 表示命中紅球,class="chartBall02" 表示命中藍球(文末獲取近 100 期數(shù)據(jù)樣本)。
<tr><td class="c_fbf5e3 bd_rt_a">2021090</td>
<td class="yl01" style="font-size:xx-small">1</td>
<td class="yl01" style="font-size:xx-small">1</td>
<td class="yl01" style="font-size:xx-small">8</td>
<td class="yl01" style="font-size:xx-small">2</td>
<td class="chartBall01">05</td>
<td class="chartBall01">06</td>
<td class="yl01" style="font-size:xx-small">1</td>
<td class="yl01" style="font-size:xx-small">4</td>
<td class="yl01" style="font-size:xx-small">6</td>
<td class="yl01" style="font-size:xx-small">4</td>
<td class="yl01" style="font-size:xx-small">5</td>
<td class="chartBall01">12</td>
<td class="yl01" style="font-size:xx-small">1</td>
<td class="chartBall01">14</td>
<td class="yl01" style="font-size:xx-small">2</td>
<td class="yl01" style="font-size:xx-small">2</td>
<td class="yl01" style="font-size:xx-small">13</td>
<td class="yl01" style="font-size:xx-small">9</td>
<td class="yl01" style="font-size:xx-small">2</td>
<td class="yl01" style="font-size:xx-small">5</td>
<td class="yl01" style="font-size:xx-small">6</td>
<td class="yl01" style="font-size:xx-small">9</td>
<td class="yl01" style="font-size:xx-small">1</td>
<td class="yl01" style="font-size:xx-small">1</td>
<td class="yl01" style="font-size:xx-small">7</td>
<td class="yl01" style="font-size:xx-small">2</td>
<td class="chartBall01">27</td>
<td class="chartBall01">28</td>
<td class="yl01" style="font-size:xx-small">4</td>
<td class="yl01" style="font-size:xx-small">13</td>
<td class="yl01" style="font-size:xx-small">12</td>
<td class="yl01" style="font-size:xx-small">8</td>
<td class="yl01" style="font-size:xx-small">7</td>
<td class="v_line"></td>
<td class="yl01" style="font-size:xx-small">4</td>
<td class="yl01" style="font-size:xx-small">5</td>
<td class="yl01" style="font-size:xx-small">42</td>
<td class="yl01" style="font-size:xx-small">3</td>
<td class="yl01" style="font-size:xx-small">8</td>
<td class="yl01" style="font-size:xx-small">2</td>
<td class="yl01" style="font-size:xx-small">16</td>
<td class="chartBall02">08</td>
<td class="yl01" style="font-size:xx-small">10</td>
<td class="yl01" style="font-size:xx-small">13</td>
<td class="yl01" style="font-size:xx-small">54</td>
<td class="yl01" style="font-size:xx-small">1</td>
<td class="yl01" style="font-size:xx-small">11</td>
<td class="yl01" style="font-size:xx-small">31</td>
<td class="yl01" style="font-size:xx-small">18</td>
<td class="yl01" style="font-size:xx-small">25</td>
</tr>
<tr>
<td class="c_fbf5e3 bd_rt_a">2021091</td>
<td class="yl01" style="font-size:xx-small">2</td>
<td class="yl01" style="font-size:xx-small">2</td>
<td class="yl01" style="font-size:xx-small">9</td>
<td class="chartBall01">04</td>
<td class="yl01" style="font-size:xx-small">1</td>
<td class="chartBall01">06</td>
<td class="yl01" style="font-size:xx-small">2</td>
<td class="yl01" style="font-size:xx-small">5</td>
<td class="yl01" style="font-size:xx-small">7</td>
<td class="yl01" style="font-size:xx-small">5</td>
<td class="yl01" style="font-size:xx-small">6</td>
<td class="yl01" style="font-size:xx-small">1</td>
<td class="yl01" style="font-size:xx-small">2</td>
<td class="yl01" style="font-size:xx-small">1</td>
<td class="yl01" style="font-size:xx-small">3</td>
<td class="chartBall01">16</td>
<td class="yl01" style="font-size:xx-small">14</td>
<td class="yl01" style="font-size:xx-small">10</td>
<td class="yl01" style="font-size:xx-small">3</td>
<td class="yl01" style="font-size:xx-small">6</td>
<td class="yl01" style="font-size:xx-small">7</td>
<td class="yl01" style="font-size:xx-small">10</td>
<td class="yl01" style="font-size:xx-small">2</td>
<td class="chartBall01">24</td>
<td class="yl01" style="font-size:xx-small">8</td>
<td class="chartBall01">26</td>
<td class="yl01" style="font-size:xx-small">1</td>
<td class="yl01" style="font-size:xx-small">1</td>
<td class="yl01" style="font-size:xx-small">5</td>
<td class="yl01" style="font-size:xx-small">14</td>
<td class="yl01" style="font-size:xx-small">13</td>
<td class="yl01" style="font-size:xx-small">9</td>
<td class="chartBall01">33</td>
<td class="v_line"></td>
<td class="yl01" style="font-size:xx-small">5</td>
<td class="yl01" style="font-size:xx-small">6</td>
<td class="yl01" style="font-size:xx-small">43</td>
<td class="yl01" style="font-size:xx-small">4</td>
<td class="yl01" style="font-size:xx-small">9</td>
<td class="yl01" style="font-size:xx-small">3</td>
<td class="yl01" style="font-size:xx-small">17</td>
<td class="yl01" style="font-size:xx-small">1</td>
<td class="yl01" style="font-size:xx-small">11</td>
<td class="yl01" style="font-size:xx-small">14</td>
<td class="yl01" style="font-size:xx-small">55</td>
<td class="yl01" style="font-size:xx-small">2</td>
<td class="yl01" style="font-size:xx-small">12</td>
<td class="yl01" style="font-size:xx-small">32</td>
<td class="yl01" style="font-size:xx-small">19</td>
<td class="chartBall02">16</td>
</tr>
三、解析實現(xiàn)
1、數(shù)據(jù)結構
為了便于表示球的命中與顏色、數(shù)值,我們可以按以下規(guī)則映射:
那么先用美麗湯把需要的內容撈出來,把所有 <td> 標簽中表示名字與色號的內容取出,按上述規(guī)則映射表示。
soup = BeautifulSoup(res_table, "html.parser")
item_lst = []
for td in soup.find_all('td'):
cls = td['class'][0]
num = td.string
if cls in ['yl01', 'chartBall01', 'chartBall02']:
item_lst.append('-'.join([cls, num]))
print(item_lst[:10])
輸出前 10 個預覽如下:
['yl01-3', 'yl01-5', 'chartBall01-03', 'yl01-5', 'yl01-1', 'yl01-5', 'chartBall01-07', 'yl01-9', 'yl01-6', 'yl01-6']
但這僅僅是一個超長列表,在此基礎上處理起來還找不到頭緒,至少要轉變成和網(wǎng)頁上結構一致的矩陣才好理解吧,那么可以想到利用 numpy 矩陣。先是用 np.array 將普通列表轉為 numpy 數(shù)組,再利用 reshape 將一維數(shù)組轉為二維數(shù)組,即 100 期 X 49 個球的矩陣。
array = np.array(item_lst).reshape(100, 49)
如圖,numpy 矩陣的每一行與原頁面結構對應。
但我們想要進行的是縱向比較分析,比較各期之間的關系,所以還需要再對矩陣進行行列轉置。
array_T = array.T # 矩陣轉置,一個元素對應一列
此時,array_T 中的每一個元素即表示某一色號的近 100 期情況。如果想看紅1 球,則是 array_T[0];如果想看紅2 球,則是 array_T[1];如果想看藍1 球,則是 array_T[33](因為紅球總共有 33 個,故第一個藍球列的索引為 33)。為了便于選球,我們可以寫一個映射方法:
def trans_col(txt): # 翻譯列索引號,如紅1=0,紅33=32,藍1=33,藍16=48
if "紅" in txt:
col = int(txt.replace('紅', '')) - 1
else:
col = int(txt.replace('藍', '')) + 32
return col
接下來就可以正式開始實現(xiàn)統(tǒng)計分析的需求啦!
2、遺漏統(tǒng)計
將轉置矩陣和指定色號球所在列傳入,獲取該列后加入一個結束標記,因至少要出現(xiàn) 1 次未命中 +1 次命中才判定為遺漏 1 期,所以從該列的第二項數(shù)據(jù)開始判斷,若其不等于前一項的值,且當前項為命中,則記錄前一項的值(遺漏期數(shù))。之后將記錄列表中的表示遺漏的標記 yl01 去除,僅保留期數(shù)。
def fun_miss(array, col): # 統(tǒng)計該列中遺漏后命中的次數(shù)
line = array[col].tolist()
order_grp = []
for i, v in enumerate(line):
if i > 0:
if v != line[i - 1] and 'chart' in v:
order_grp.append(line[i - 1])
order_grp = [i.replace('yl01-', '') for i in order_grp]
c = dict(Counter(order_grp))
result = sorted(c.items(), key=lambda x: int(x[0]))
for i in result:
print(f"遺漏{i[0]}期后中的次數(shù)有{i[1]}次")
fun_miss(array_T, trans_col("紅1")) # 執(zhí)行
統(tǒng)計排序后輸出如下:
遺漏1期后中的次數(shù)有4次遺漏2期后中的次數(shù)有2次遺漏3期后中的次數(shù)有3次遺漏5期后中的次數(shù)有2次遺漏7期后中的次數(shù)有2次遺漏8期后中的次數(shù)有1次遺漏9期后中的次數(shù)有2次遺漏13期后中的次數(shù)有1次
3、連續(xù)重號統(tǒng)計
與遺漏統(tǒng)計相同,傳入兩個參數(shù),先確定要選取的色號列。當前項等于前一項,且當前項為命中時表示重號,連續(xù)重號時 count 計數(shù) +1,當出現(xiàn)不滿足重號條件時表示連續(xù)重號中斷,記錄連續(xù)次數(shù),并將計數(shù)清零,待下一輪重號出現(xiàn)時重新計數(shù)。
def fun_repeat(array, col): # 統(tǒng)計該列中的重號次數(shù)
line = array[col].tolist()
count_grp = []
count = 0
for i, v in enumerate(line):
if i > 0:
if v == line[i-1] and 'chart' in v:
count += 1
elif count > 0:
count_grp.append(count)
count = 0
c = dict(Counter(count_grp))
result = sorted(c.items(), key=lambda x: x[0])
for i in result:
print(f"連續(xù)重號{i[0]}次的有{i[1]}次")
fun_repeat(wt, trans_col("紅2")) # 執(zhí)行
統(tǒng)計排序后輸出如下:
連續(xù)重號1次的有1次連續(xù)重號2次的有1次
4、重號前的遺漏統(tǒng)計
因要出現(xiàn)重號+遺漏才算入,所以至少從第三項數(shù)據(jù)開始判定。
def fun_return(array, col): # 統(tǒng)計該列中重號前的遺漏次數(shù)
line = array[col].tolist()
order_grp = []
for i, v in enumerate(line):
if i > 1:
if v == line[i - 1] and v != line[i - 2] and 'chart' in v:
order_grp.append(line[i - 2])
order_grp = [i.replace('yl01-', '') for i in order_grp]
c = dict(Counter(order_grp))
result = sorted(c.items(), key=lambda x: int(x[0]))
for i in result:
print(f"重號前遺漏{i[0]}期的有{i[1]}次")
fun_return(wt, trans_col("紅1")) # 執(zhí)行
統(tǒng)計排序后輸出如下:
重號前遺漏2期的有1次
四、小結
emmmm...不過如此看來,單單分析一個球是不夠滴,還要和其他色號深入對比,有興趣的同學自己嘗試吧哈哈哈!~這里是我命由天不由我的 Seon塞翁,下篇再見!
溫馨提示:本文僅做數(shù)據(jù)處理技術討論,不構成任何資金投入建議!
推薦閱讀:
入門: 最全的零基礎學Python的問題 | 零基礎學了8個月的Python | 實戰(zhàn)項目 |學Python就是這條捷徑
干貨:爬取豆瓣短評,電影《后來的我們》 | 38年NBA最佳球員分析 | 從萬眾期待到口碑撲街!唐探3令人失望 | 笑看新倚天屠龍記 | 燈謎答題王 |用Python做個海量小姐姐素描圖 |碟中諜這么火,我用機器學習做個迷你推薦系統(tǒng)電影
趣味:彈球游戲 | 九宮格 | 漂亮的花 | 兩百行Python《天天酷跑》游戲!
AI: 會做詩的機器人 | 給圖片上色 | 預測收入 | 碟中諜這么火,我用機器學習做個迷你推薦系統(tǒng)電影
小工具: Pdf轉Word,輕松搞定表格和水印! | 一鍵把html網(wǎng)頁保存為pdf!| 再見PDF提取收費! | 用90行代碼打造最強PDF轉換器,word、PPT、excel、markdown、html一鍵轉換 | 制作一款釘釘?shù)蛢r機票提示器! |60行代碼做了一個語音壁紙切換器天天看小姐姐!|
年度爆款文案
點閱讀原文,領AI全套資料!


