我们从中国体彩网爬取历史开奖数据。
由于网站属于静态网页,很容易就能获取到想要的内容,所以爬取过程就不详细介绍。
直接上代码:
import requests
from bs4 import BeautifulSoup as bs
import threading
import queue
class get_history(threading.Thread):
def __init__(self,task_q,result_q):
super().__init__()
self.task_queue=task_q
self.result_queue=result_q
def run(self):
while True:
if not self.task_queue.empty():
page=self.task_queue.get()
one_result=self.crawl(page)
self.result_queue.put(one_result)
self.task_queue.task_done()
print('##第{}页爬取完毕~~~~~'.format(page))
else:
break
def crawl(self,page):
url = 'http://www.lottery.gov.cn/historykj/history_{}.jspx?_ltype=dlt'.format(page)
headers = {
'user-agent': 'Mozilla / 5.0(Windows NT 10.0;Win64;x64) AppleWebKit / 537.36(KHTML, likeGecko) Chrome / 75.0.3770.142Safari / 537.36',
'Upgrade-Insecure-Requests': '1',
'Host': 'www.lottery.gov.cn'
}
r = requests.get(url, headers=headers)
text = bs(r.text, 'lxml')
result = text.find_all('div', class_='result')
result = result[0].find_all('tbody')
result = result[0].find_all('td')
result_list = []
for item in result:
result_list.append(item.get_text())
one_page=[]
one_page.append([result_list[19]] + result_list[0:8])
for i in range(1, 20):
open_data = result_list[19 + (20 * i)]
number_list = result_list[20 + (20 * (i - 1)):21 + (20 * (i - 1)) + 7]
# print([open_data] + number_list)
one_page.append([open_data] + number_list)
return one_page
if __name__ == '__main__':
task_queue=queue.Queue()
result_queue=queue.Queue()
for i in range(1,94):
task_queue.put(i)
crawl=get_history(task_queue,result_queue)
crawl.setDaemon(True)
crawl.start()
task_queue.join()
with open('history.txt','a') as f :
while not result_queue.empty():
for one in result_queue.get():
one_line=''
for item in one:
one_line+=item
f.write(one_line+'\n')
由于最近多线程和队列用的比较多,所以这里一开始就也想用多线程+队列,但是后来发现,因为本身网页就是静态的获取数据非常简单,加上总共也才90多页,根本不需要多线程,单线程就能很快爬完。既然写了就当作对多线程和队列的巩固练习吧~
将爬取到的数据保存到history.txt
总共获取到了1860条数据,每条就是一期开奖结果,相当于1860期,从2007年到2019年十二年来的开奖数据。
利用pyecharts进行可视化分析
from collections import Counter
from pyecharts.charts import Bar,Page
from pyecharts import options as opts
def number_analyse():
red_balls = []
blue_balls = []
with open('history.txt', 'r') as f:
for i in range(1860):
oneLine_data = f.readline().strip()
red_balls.extend([int(oneLine_data[15 + (2 * i):15 + (2 * (i + 1))]) for i in range(5)])
blue_balls.append(int(oneLine_data[-4:-2]))
blue_balls.append(int(oneLine_data[-2:]))
red_counter = Counter(red_balls)
blue_counter = Counter(blue_balls)
print(red_balls)
print(blue_balls)
print(red_counter)
print(blue_counter)
print(red_counter.most_common())
print(blue_counter.most_common())
red_dict={}
blue_dict={}
for i in red_counter.most_common():#使用collections模块的counter统计红球和蓝球各个号码的出现次数
red_dict['{}'.format(i[0])]=i[1]
for j in blue_counter.most_common():
blue_dict['{}'.format(j[0])]=j[1]
print(red_dict)
print(blue_dict)
red_list=sorted(red_counter.most_common(),key=lambda number:number[0])#对红蓝球号码和次数重新进行排序
blue_list=sorted(blue_counter.most_common(),key=lambda number:number[0])
print(red_list)
print(blue_list)
red_bar=Bar()
red_x=['{}'.format(str(x[0])) for x in red_list]
red_y=['{}'.format(str(x[1])) for x in red_list]
red_bar.add_xaxis(red_x)
red_bar.add_yaxis('红色球出现次数',red_y)
red_bar.set_global_opts(title_opts=opts.TitleOpts(title='大乐透彩票',subtitle='近12年数据'),toolbox_opts=opts.ToolboxOpts()
,yaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(formatter="{value}/次")),
xaxis_opts=opts.AxisOpts(name='开奖号码'))
red_bar.set_series_opts(markpoint_opts=opts.MarkPointOpts(
data=[opts.MarkPointItem(type_='max',name='最大值'),opts.MarkPointItem(type_='min',name='最小值')]
))
blue_bar=Bar()
blue_x=['{}'.format(str(x[0])) for x in blue_list]
blue_y=['{}'.format(str(x[1])) for x in blue_list]
blue_bar.add_xaxis(blue_x)
blue_bar.add_yaxis('蓝色球出现次数',blue_y,itemstyle_opts=opts.ItemStyleOpts(color='blue'))
blue_bar.set_global_opts(title_opts=opts.TitleOpts(title='大乐透彩票',subtitle='近12年数据'),toolbox_opts=opts.ToolboxOpts()
,yaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(formatter="{value}/次")),
xaxis_opts=opts.AxisOpts(name='开奖号码'))
blue_bar.set_series_opts(markpoint_opts=opts.MarkPointOpts(
data=[opts.MarkPointItem(type_='max',name='最大值'),opts.MarkPointItem(type_='min',name='最小值')]
))
page=Page(page_title='大乐透历史开奖数据分析',interval=3)
page.add(red_bar,blue_bar)
page.render('大乐透历史开奖数据分析.html')
最后将图表保存到“大乐透历史开奖数据分析.html”,然后使用浏览器打开
可以看到红色球中出现次数最多的是29,总共出现了352次,出现最少的是16,共出现了208次。
而蓝色球出现最多的是10,共出现343次,出现最少的是1,共出现292次。
关于sklearn的使用参考这篇文章:https://blog.csdn.net/lilianforever/article/details/53780613
一组开奖号码有7个数字,所以分别建立了7个模型,每个位置的开奖号码为一个模型,使用每期的开奖日期和期数当作特征值,每个位置的开奖号码数字为标签直对模型进行训练。
之后对每个模型分别输入下一期开奖日期和期号进行预测每个位置的号码,然后将7个号码组合起来就是最后预测的开奖号码。
from sklearn import svm
def forecast():
data=[]
period=[]
first_num=[]
second_num=[]
third_num=[]
fourth_num=[]
fifth_num=[]
sixth_num=[]
seventh_num=[]
with open('history.txt', 'r') as f:
for i in range(1860):
oneLine_data = f.readline().strip()
data.append(int(oneLine_data[0:10].replace('-','')))
period.append(int(oneLine_data[10:15]))
first_num.append(int(oneLine_data[15:17]))
second_num.append(int(oneLine_data[17:19]))
third_num.append(int(oneLine_data[19:21]))
fourth_num.append(int(oneLine_data[21:23]))
fifth_num.append(int(oneLine_data[23:25]))
sixth_num.append(int(oneLine_data[25:27]))
seventh_num.append(int(oneLine_data[27:29]))
# print(data)
# print(period)
# print(first_num)
# print(second_num)
# print(third_num)
# print(fourth_num)
# print(fifth_num)
# print(sixth_num)
# print(seventh_num)
x=[]
for j in range(len(data)):
x.append([data[j],period[j]])
first_model=svm.SVR(gamma='auto')
second_model=svm.SVR(gamma='auto')
third_model=svm.SVR(gamma='auto')
fourth_model=svm.SVR(gamma='auto')
fifth_model=svm.SVR(gamma='auto')
sixth_model=svm.SVR(gamma='auto')
seventh_model=svm.SVR(gamma='auto')
model_list=[first_model,second_model,third_model,fourth_model,fifth_model,sixth_model,seventh_model]
y_list=[first_num,second_num,third_num,fourth_num,fifth_num,sixth_num,seventh_num]
for k in range(7):
model_list[k].fit(x,y_list[k])
res_list=[]
for model in model_list:
res=model.predict([[20190803,19089]]).tolist()
res_list.append(res)
print(res_list)
#res=first_model.predict([[20190729,19087]])
#print(res)
forecast()
得到下期的预测号码:
关于深度学习,我也没学过,对于一些算法、原理我也暂时还不是很懂。这里只是稍微了解了一下就选了个模型直接进行使用。如果要更加严谨的操作,需要对多个模型进行交叉验证,选择出最优模型,和对模型做进一步调优,这里就不折腾了(其实是还不会)
这个预测彩票其实并不靠谱,原因我想大家都懂的~,而且开奖号码跟期数和开奖日期并没有半点相关性,用开奖期数+开奖日期来进行深度学习和预测本来就是毫无意义的事情。就当是娱乐娱乐的同时巩固和练习相关的python知识。
但是偶尔花个8块10块买个几注彩票(千万不要沉迷~)还是可以的,万一哪天踩了狗屎运中了,说不定就此改变命运 ~,俗话说梦想还是要有的,万一实现了呢!