python寫一個雙色球計算器

来源:https://www.cnblogs.com/xiu123/archive/2018/09/13/9638214.html
-Advertisement-
Play Games

首先聲明,賭博一定不是什麼好事,也完全沒有意義,不要指望用彩票發財。之所以寫這個,其實是用來練手的,可以參考這個來預測一些其他的東西,意在拋磚引玉。 啰嗦完了,馬上開始,先上偽代碼 打開網址 讀取內容內容解析 根據源碼得到需爬取內容 1、開獎日期:2018年8月26日 2、紅球 <li class= ...


首先聲明,賭博一定不是什麼好事,也完全沒有意義,不要指望用彩票發財。之所以寫這個,其實是用來練手的,可以參考這個來預測一些其他的東西,意在拋磚引玉。

啰嗦完了,馬上開始,先上偽代碼

打開網址

  讀取內容
內容解析

  根據源碼得到需爬取內容

  1、開獎日期:2018年8月26日

  2、紅球

                                <li class="ball_red">03</li>

                                <li class="ball_red">07</li>

                                <li class="ball_red">08</li>

                                <li class="ball_red">14</li>

                                <li class="ball_red">25</li>

                                <li class="ball_red">32</li>

  3、籃球

                                    <li class="ball_blue">06</li>

打開資料庫連接

  爬取內容寫入資料庫

    共3個欄位

    1、開獎日期

    2、紅球,紅球使用分號“;”分隔,方便調用和導出

    3、籃球

在寫腳本前,建議先寫偽代碼,偽代碼格式不是固定的,隨自己喜好,主要就是在思維及演算法落地前,把整個輪廓理清,可以有效降低都快寫完了,發現前面有錯誤,結果導致整個腳本全部更新一遍這種事

的發生概率

偽代碼解讀:

    共分為兩個功能塊

        一就是抓取彩票數據,這個使用爬蟲實現,分別抓取開獎日期、紅球區、籃球區,因為考慮雙色球的數據量比較龐大,所以這次使用資料庫進行存儲,選用的是免費又好用的mysql資料庫,資料庫介面文件使用MySQLdb,這個我以後會單獨寫一個說明,當然你也可以用文檔存儲,或者選擇別的資料庫比如oracle或者nosql的mangodb

        二是用來分析彩票的,即使用彩票數據進行下一期的彩票預測,本次選用的是二項分佈,這個在之前的演算法裡面有,就不重覆說明瞭

下麵先上腳本,再對腳本進行說明

#!/usr/bin/python
# coding: UTF-8

'''
打開網址
  讀取內容
內容解析
  根據源碼得到需爬取內容
  1、開獎日期:2018年8月26日
  2、紅球
                                <li class="ball_red">03</li>
                                <li class="ball_red">07</li>
                                <li class="ball_red">08</li>
                                <li class="ball_red">14</li>
                                <li class="ball_red">25</li>
                                <li class="ball_red">32</li>
  3、籃球
                                <li class="ball_blue">06</li>
打開資料庫連接
  爬取內容寫入資料庫
    共3個欄位
    1、開獎日期
    2、紅球,紅球使用分號“;”分隔,方便調用和導出
    3、籃球
create table tow_color_ball(open_date varchar(10),red_n varchar(20),blue_n varchar(2))
'''

import urllib
import urllib2
import re
import numpy as np
import operator
import MySQLdb

# 連接mysql
def conn_db():
  db = 'pythondb'
  host = 'localhost'
  iuser = 'xxx'
  passwd = 'xxxxxx'
  conn = MySQLdb.connect(db = db, host = host, user = iuser, passwd = passwd)
  cursor = conn.cursor()
  return cursor

# 處理網頁獲取頁面源碼
def get_html_values(url):
  url_open = urllib.urlopen(url)
  url_read = url_open.read()
  return url_read

# 處理源碼,獲取日期、紅球、籃球
def manage_html(html_values):
  red_no_re = re.compile('(?<=\<li class\=\"ball_red\"\>)[0-9]+(?=\<\/li\>)')
  blue_no_re = re.compile('(?<=\<li class\=\"ball_blue\"\>)[0-9]+(?=\<\/li\>)')
  date_re = re.compile('(?<=開獎日期:)[0-9]+年[0-9]+月[0-9]+日')
  red_no_list = re.findall(red_no_re,html_values)
  red_numbers = ';'.join(red_no_list)
  blue_number = re.search(blue_no_re,html_values)
  blue_number = blue_number.group()
  date_value = re.search(date_re,html_values)
  date_value = date_value.group()
  return date_value, red_numbers, blue_number

# 可惡的日期,竟然是YYYY年MM月DD日,需要改成YYYY-MM-DD
def manage_date(date_value):
  date_value = date_value.replace('','-').replace('','-').replace('','')
  return date_value

# 處理頁面編號,每次編號-1,也就是說end_page要小於url中的頁碼
def get_page(url,end_page):
  url_num = re.search('(?<=\/)[0-9]+(?=\.)',url)
  url_num = url_num.group()
  if int(end_page) > int(url_num):
    return 'end'
  url_num_1 = int(url_num) - 1
  url = url.replace(url_num,str(url_num_1))
  return url

# 查看庫中是否已存在開獎日期,防止重覆寫入
def check_open_date(open_date):
  conn = conn_db()
  check_sql = 'select 1 from tow_color_ball where open_date = %r' %open_date
  conn.execute(check_sql)
  excur = conn.fetchall()
  conn.close()
  #如過未查到excur == ()
  return excur

# 寫入資料庫
def write_db(date_value, red_numbers, blue_number):
  conn = conn_db()
  in_sql = "insert into tow_color_ball(open_date,red_n,blue_n) values(%r,%r,%r)" %(date_value, red_numbers, blue_number)
  conn.execute(in_sql)
  conn.execute('commit')
  conn.close()

# 彩票主程式,用來爬取彩票號碼
def ball_main(url,end_page):
  while True:
    html_values = get_html_values(url)
    date_value, red_numbers, blue_number = manage_html(html_values)
    date_value = manage_date(date_value)
    data_check = check_open_date(date_value)
    if data_check == ():
      write_db(date_value, red_numbers, blue_number)
    url = get_page(url,end_page)
    if url == 'end':
      print 'url_page已到達end_page,獲取完成'
      return 0

# 二項分佈演算法
class binomial_class(object):
  def __init__(self,case_count,real_count,p):
    self.case_count = case_count
    self.real_count = real_count
    self.p = p

  def multiply_fun(self,xlist):
    n = 1
    for x in xlist:
      n *= x
    return n
 
  def fact_fun(self,n):
    if n == 0:
      return 1
    n += 1
    fact_list = [i for i in range(1,n)]
    fact_num = self.multiply_fun(fact_list)
    return fact_num

  def c_n_x(self):
    fact_n = self.fact_fun(self.case_count)
    fact_x = self.fact_fun(self.real_count)
    fact_n_x = self.fact_fun(self.case_count - self.real_count)
    c_n_x_num = float(fact_n) / (fact_x * fact_n_x)
    return c_n_x_num

  def binomial_fun(self):
    c_n_k_num = self.c_n_x()
    pi = (self.p ** self.real_count) * ((1 - self.p) ** (self.case_count - self.real_count))
    binomial_num = c_n_k_num * pi
    return binomial_num

# 從庫里獲取彩票信息
def get_ball_infomation(start_dt,end_dt):
  conn = conn_db()
  sql = "select red_n,blue_n from tow_color_ball where date_format(open_date,'%%Y-%%m-%%d') >= %r and date_format(open_date,'%%Y-%%m-%%d') <= %r" %(start_dt,end_dt)
  conn.execute(sql)
  excur = conn.fetchall()
  conn.close()
  case_array = np.array(excur)
  row_count = case_array.shape[0]
  col_count = case_array.shape[1]
  red_ball_array = case_array[:,0]
  blue_ball_array = case_array[:,1]
  return red_ball_array,blue_ball_array,row_count,col_count

# 統計每個號碼球的出現次數,這個應該在資料庫里做,先放這,以後改
def every_ball_count(ball_array):
  ball_list = []
  for ball_char in ball_array:
    ball_list += ball_char.split(';')
  ball_count = {}
  for ball_num in ball_list:
    if ball_num in ball_count:
      ball_count[ball_num] += 1
    else:
      ball_count[ball_num] = ball_count.get(ball_num,0) + 1
  return ball_count

# 數據分析主函數,樣本量必須大於等於7,否則不進行處理
def analysis_main(start_dt,end_dt):
  red_ball_array,blue_ball_array,row_count,col_count = get_ball_infomation(start_dt,end_dt)
  if row_count < 7:
    print '樣本量不足以支持分析'
    return 1
  red_count_dict = every_ball_count(red_ball_array)
  blue_count_dict = every_ball_count(blue_ball_array)
  for red_case in red_count_dict:
    red_rate = binomial_class((red_count_dict[red_case] + 1),(row_count + 1),0.5)
    red_count_dict[red_case] = red_rate.binomial_fun()
  for blue_case in blue_count_dict:
    blue_rate = binomial_class((blue_count_dict[blue_case] + 1),(row_count + 1),0.5)
    blue_count_dict[blue_case] = blue_rate.binomial_fun()
  sorted_red_count = sorted(red_count_dict.iteritems(),key=operator.itemgetter(1),reverse=True)
  sorted_blue_count = sorted(blue_count_dict.iteritems(),key=operator.itemgetter(1),reverse=True)
  print sorted_blue_count[0]
  print '選擇紅球是:'
  n = 1
  for key,value in sorted_red_count:
    if n == 7:
      break
    print '%s,%s' %(key,str(value))
    n += 1
  print '選擇藍球是'
  print '%s,%s' %(sorted_blue_count[0][0],str(sorted_blue_count[0][1]))

if __name__ == '__main__':
  n = ''
  while n != '1' or n != '2':
    input_n = raw_input('''
請選擇需要進行的功能
1、爬取頁面的球號
2、進行球號分析
輸入quit退出
請選擇: ''')
    if input_n == '1':
      url = raw_input('''
請輸入需要爬取的地址(此為開始地址,因此建議選擇頁碼較大的地址)
輸入: ''')
      end_page = raw_input('''
輸入結束頁碼
(註意:如果結束頁碼大於輸入地址的頁碼,則不會爬取任何頁面)
輸入: ''')
      ball_main(url,end_page)
    elif input_n == '2':
      analysis_main('2018-08-15','2018-09-09')
    elif input_n == 'quit':
      exit(0)

腳本共分兩個功能塊,一個是爬蟲,用來爬取雙色球號碼,另一個是分析,使用二項分佈對已抓取數據進行概率計算

先說說爬蟲,依然是先觀察頁面

看過之前初級爬蟲的同學應該對這個很熟悉,要爬的是1的地方,觀察位置2和位置3,不難看出,每期占用一個頁面,那麼只要利用翻頁,每次頁碼-1即可,下麵看看1位置的源代碼

在源碼中搜索開獎號碼,找到紅圈位置,這個和偽代碼中寫的一樣,現在看爬取正則

red_no_re = re.compile('(?<=\<li class\=\"ball_red\"\>)[0-9]+(?=\<\/li\>)')

blue_no_re = re.compile('(?<=\<li class\=\"ball_blue\"\>)[0-9]+(?=\<\/li\>)')

date_re = re.compile('(?<=開獎日期:)[0-9]+年[0-9]+月[0-9]+日')
分別爬取紅球,籃球,日期
下麵的事就好辦了,將爬好的數據存入資料庫,連接mysql,包含4個參數

  db = 'pythondb'
  host = 'localhost'
  iuser = 'xxx'
  passwd = 'xxxxxx'

分別是連接資料庫、連接地址、用戶名、密碼

因為在每期開獎之後都需要爬一次新的號碼,所以我沒有把這個做成一次性的,用戶需要輸入開始爬取頁面,以及結束頁面編號,當爬取到結束編號頁面後則停止

為防止重覆爬入數據,導致資料庫數據重覆,因此在數據入庫前需要對庫數據進行驗證需要入庫數據是否已存在,詳見check_open_date函數

最後需要註意的是,在寫入完畢後應關閉資料庫連接,因為mysql預設自動commit,因此我這個沒有單獨commit的sql,如果是oracle不要忘記加這個

接下來是分析模塊,二項分佈為方便管理,單獨寫了個類,以後也可以單獨調用,這個用法我之前的文裡面有說明,就不再說了。這裡有幾個功能說明下

1、與爬蟲一樣,分析也是需要寫入開始日期和結束日期的,且從庫中獲取case必須大於7個,否則考慮樣本不足,無法分析

2、將每個號碼在時間段的出現頻次進行統計並+1,即二項分佈的成功k次數

3、獲取時間段內的期數並+1,即二項分佈的實驗次數

4、因為每個號碼只有兩種可能,要麼出現,要麼不出現,因此事件的成功率是0.5

結果是這樣,看到概率最高的是2.34863516114e-08,這是一個科學技術法,大約是0.00000002349,也就是1/5000萬,因此這個概率沒有任何意義,當然你也可以嘗試買2塊錢的,買不中別賴我啊,哈哈

細心的同學可能註意到了,算出來的最後兩個紅球概率是一樣的,舉個例子C(5,2)其實和C(5,3)的組合數是一樣的,那麼二項分佈的概率當然也一樣,這樣就需要用到泊松分佈,加入歷史平均值的計算,因為這個需要在庫中單獨建表,還沒有時間做這個事,因此沒有加入這項計算,如果各位有興趣可以自己嘗試把這塊加上,等我有時間了,我也會把這個寫出來完善下的


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 輸出: 1.開啟絕對定位,會使元素脫離文檔流; 2、開啟絕對定位以後,如果不設置偏移量,則元素的位置不會發生變化; 3、相對於瀏覽器視窗進行定位; 開啟box3的定位並把box2作為box3的子元素: 輸出: 若有祖先元素開啟了定位(一般情況,開啟了子元素的絕對定位都會同時開啟父元素的相對定位); ...
  • 背景 現在的前端項目越來越複雜,在不同的客戶端會產生各種在開發人員機器上不會出現的問題。當用戶報告一個問題給開發人員的時候,開發人員無法直接定位問題。在此前,聽過一次鵝廠的前端人員,他們對QQ裡面的網頁監控的一個講座,深有感觸。但是鵝廠是自己開發了一系統,從開發到運維到錯誤分析,是一整套的體系。對於 ...
  • 以下代碼可放在一個js文件中,以便通用: //獲取指定表單中指定標簽對象 function getElements(formId, label) { var form = document.getElementById(formId);/* 獲取表單引用(對象) */ var elements = ...
  • 第一種:字元串拆分法 window.location.href 或者 location.href 或者 window.location 獲得地址欄中的所有內容 decodeURI()可以解碼地址欄中的數據 恢復中文數據 window.search 獲得地址欄中問號及問號之後的數據 第二種:正則匹配法 ...
  • 有一個需求要為document對象綁定click事件來是想隱藏提示框的交互功能,於是小白寫瞭如下代碼: 同事小銘看了看代碼說: “首先,你為document 綁定了click事件,但是onclick是DOM0級事件,也就是說這種方式綁定的時間相當於為元素綁定了一個時間方法, 所以如果團隊中的其他人再 ...
  • markdown簡介 什麼是Markdown?Markdown是一種輕量級的「標記語言」,通常為程式員群體所用,目前它已是全球最大的技術分享網站 GitHub 和技術問答網站 StackOverFlow 的御用書寫格式。 就是這十個不到的標記符號,卻能讓人優雅地沉浸式記錄,專註內容而不是糾結排版,達 ...
  • 一.JDK的下載和安裝 這裡提供32位和64位JDK的下載鏈接 百度網盤:https://pan.baidu.com/s/1xtiVOE2gPCvlGCTy0vfBaw 密碼:c5m4 官網:https://www.oracle.com/technetwork/java/javase/downloa ...
  • 做Qt開發的會知道QLineEdit是預設沒有clicked事件的,但是Qt有很好的一套信號/槽機制,而且Qt是基於C++面向對象的思想來設計的,那麼我們就很容易通過自己定義一些類,重寫QLineEdit的一些方法去實現沒有的方法,比如clicked事件.本人就以QLineEdit 添加clicke ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...