福利彩票-双色球爬虫数据分析实战
Ⅰ.爬取数据的初衷:心血来潮,纯属娱乐,实战的过程其实也是探索的过程,难免冗余,多多包涵!
备注:
双色球是中国福利彩票的一种玩法。中国福利彩票“双色球”是一种由中国福利彩票发行管理中心统一组织发行,在全国销售联合发行的“乐透型”福利彩票。2003年2月16日起在全国联网销售。采用计算机网络系统发行销售,定期电视开奖。参与“双色球”销售的省级福利彩票发行中心在中福彩中心的直接领导下,负责对本地区的“双色球”销售活动实施具体的组织和管理。“双色球”彩票实行自愿购买,凡购买者均被视为同意并遵守本规则----来源:百度文库
,也是是说数据只从2003年开始喽!
Ⅱ.工具:
- 语言: python | sql
- 工具包:
- urllib | pymysql | re | zlib
- 数据库:mysql
Ⅲ.网站页面分析
- 百度到这个网站数据http://kaijiang.500.com/ssq.shtml
- 页面分析,需提取的数据球号及期数
- 发现网页的规律:http://kaijiang.500.com/shtml/ssq/(期数).shtml
- 如何获取所有的期数呢?F12发现有个动态加载的div块这就好办了,直接复制这一整个div块,放到本地存为文件caipiao.html
总:网页规律和需要提取的数据也有了,接下来就是爬取和分析数据了
Ⅳ.数据库建表及技巧-mysql
CREATE TABLE `tb_dou_color` (`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',`red_one` int(2) DEFAULT NULL,`red_two` int(2) DEFAULT NULL,`red_three` int(2) DEFAULT NULL,`red_four` int(2) DEFAULT NULL,`red_five` int(2) DEFAULT NULL,`red_six` int(2) DEFAULT NULL,`blue` int(2) DEFAULT NULL,`period` varchar(100) DEFAULT NULL,PRIMARY KEY (`id`),UNIQUE KEY `peroid_uniq_index` (`period`) USING HASH COMMENT '期数唯一索引'
) ENGINE=InnoDB AUTO_INCREMENT=4613 DEFAULT CHARSET=utf8mb4 COMMENT='双色球数据';
- 解释一下:
- 1.主键自增
- 2.六个红色球号,一个蓝色球号,数据类型int,这里不设为varchar是为了防止网页结构不一致,爬到错误数据,让数据库协助去除错误数据
- 3.period 字段设置唯一索引 是为补救丢失数据,在重复爬取的时候去重
Ⅴ.爬虫代码伺候:
#读取本地之前保存的div块信息,提取所有的期数页面fh=open("c:/Users/nec/Desktop/caipiao.html","r")data=fh.read()#正则匹配pat='href="(.*?)"'import re#拿到页面listres=re.compile(pat).findall(data)len(res)
爬取过程中遇到ip被封杀,所以采用代理ip爬取
import urllib.request
#定义代理函数
def use_proxy(url,proxy_addr):proxy=urllib.request.ProxyHandler({"http":proxy_addr})print(proxy_addr)opener=urllib.request.build_opener(proxy,urllib.request.HTTPHandler)urllib.request.install_opener(opener)data=urllib.request.urlopen(url,timeout=8).read()return data
百度找到免费的代理ip,不是很稳定,但也还可以用
测试代理ip是否可用:
proxy_addr="112.85.128.47:9999"
html=use_proxy("http://www.baidu.com",proxy_addr)
112.85.128.47:9999
测试链接数据库:
import pymysql
conn=pymysql.connect(host="192.168.1.188",user="root",passwd="roota123",db="douball")
sql="show tables"
conn.query(sql)
爬取网页发现,网页优化做了gzip压缩,所以网页爬取后先需要解压缩
第一轮尝试爬取-异常处理后继续
import zlib
for url in res:try:print(url)#使用代理html=use_proxy(url,proxy_addr)#解压缩decompressed_data = zlib.decompress(html ,16+zlib.MAX_WBITS)#正则匹配pattern1='<li class="ball_red">(.*?)</li>'pattern2='<li class="ball_blue">(.*?)</li>'pattern3='<font class="cfont2"><strong>(.*?)</strong>'pattern4='<span class="span_right">(.*?)</span>'reds=re.compile(pattern1).findall(str(decompressed_data))blues=re.compile(pattern2).findall(str(decompressed_data))periods=re.compile(pattern3).findall(str(decompressed_data))print(reds[0])print(blues[0])print(periods[0])sql="insert into tb_dou_color (red_one,red_two,red_three,red_four,red_five,red_six,blue,period) values ("+reds[0]+","+reds[1]+","+reds[2]+","+reds[3]+","+reds[4]+","+reds[5]+","+blues[0]+","+periods[0]+")"conn.query(sql)#批处理提交if (periods[0]-1)%100==0:conn.commit()except Exception as err:print (err)
这个过程中出现了一些异常,丢失了部分数据
- 代理服务不可用
HTTP Error 503: Service Unavailable
http://kaijiang.500.com/shtml/ssq/19055.shtml
112.80.41.86:8888
- ip被封
<urlopen error [WinError 10061] 由于目标计算机积极拒绝,无法连接。>
http://kaijiang.500.com/shtml/ssq/19055.shtml112.85.128.209:9999
<urlopen error timed out>[WinError 10054] 远程主机强迫关闭了一个现有的连接。
http://kaijiang.500.com/shtml/ssq/18127.shtml
- 浏览器请求头异常等
Error -3 while decompressing data: incorrect header check
http://kaijiang.500.com/shtml/ssq/19054.shtml
所以需求适时切换代理ip,重复爬取数据,利用数据库唯一索引去重
(1062, "Duplicate entry '19052' for key 'peroid_uniq_index'")
http://kaijiang.500.com/shtml/ssq/19051.shtml
112.80.41.86:8888
适时手动提交一下数据
conn.commit()
代理请求函数添加浏览器伪装及指定网页压缩类型:
def use_proxy(url,proxy_addr):proxy=urllib.request.ProxyHandler({"http":proxy_addr})print(proxy_addr)opener=urllib.request.build_opener(proxy,urllib.request.HTTPHandler)urllib.request.install_opener(opener)headers={"User-Agent":"Mozilla/5.0 (Windows NT 10.0; WOW64; rv:67.0) Gecko/20100101 Firefox/67.0",'Accept-Encoding':'gzip, deflate'}#opener=urllib.request.build_opener()#opener.addheaders=[headers]#data=urllib.request.urlopen(url,timeout=8).read()req=urllib.request.Request(url,headers=headers)data=urllib.request.urlopen(req).read()return data
优化后继续爬取数据:
for url in res:try:print(url)html=use_proxy(url,proxy_addr)try:decompressed_data = zlib.decompress(html ,zlib.MAX_WBITS|32)except Exception as err1:print (err1)try:decompressed_data = zlib.decompress(html ,zlib.MAX_WBITS|16)except Exception as err2:print (err2)try:decompressed_data = zlib.decompress(html)except Exception as err3:print(err3)decompressed_data = zlib.decompress(html,-zlib.MAX_WBITS)pattern1='<li class="ball_red">(.*?)</li>'pattern2='<li class="ball_blue">(.*?)</li>'pattern3='<font class="cfont2"><strong>(.*?)</strong>'pattern4='<span class="span_right">(.*?)</span>'reds=re.compile(pattern1).findall(str(decompressed_data))blues=re.compile(pattern2).findall(str(decompressed_data))periods=re.compile(pattern3).findall(str(decompressed_data))print(reds[0])print(blues[0])print(periods[0])sql="insert into tb_dou_color (red_one,red_two,red_three,red_four,red_five,red_six,blue,period) values ("+reds[0]+","+reds[1]+","+reds[2]+","+reds[3]+","+reds[4]+","+reds[5]+","+blues[0]+","+periods[0]+")"conn.query(sql)if (int(periods[0])-1)%100==0:conn.commit()except Exception as err:print (err)
爬到一大半,ip又被封了!
http://kaijiang.500.com/shtml/ssq/07098.shtml
112.85.171.116:9999
<urlopen error [WinError 10061] 由于目标计算机积极拒绝,无法连接。>
http://kaijiang.500.com/shtml/ssq/07097.shtml
切换ip,过滤已经爬取的部分,接着爬取
for url in res:patt="http://kaijiang.500.com/shtml/ssq/(.*?).shtml"index=re.compile(patt).findall(url)if int(index[0])>7098:continuetry:print(url)html=use_proxy(url,proxy_addr)try:decompressed_data = zlib.decompress(html ,zlib.MAX_WBITS|32)except Exception as err1:print (err1)try:decompressed_data = zlib.decompress(html ,zlib.MAX_WBITS|16)except Exception as err2:print (err2)try:decompressed_data = zlib.decompress(html)except Exception as err3:print(err3)decompressed_data = zlib.decompress(html,-zlib.MAX_WBITS)pattern1='<li class="ball_red">(.*?)</li>'pattern2='<li class="ball_blue">(.*?)</li>'pattern3='<font class="cfont2"><strong>(.*?)</strong>'pattern4='<span class="span_right">(.*?)</span>'reds=re.compile(pattern1).findall(str(decompressed_data))blues=re.compile(pattern2).findall(str(decompressed_data))periods=re.compile(pattern3).findall(str(decompressed_data))print(reds[0])print(blues[0])print(periods[0])sql="insert into tb_dou_color (red_one,red_two,red_three,red_four,red_five,red_six,blue,period) values ("+reds[0]+","+reds[1]+","+reds[2]+","+reds[3]+","+reds[4]+","+reds[5]+","+blues[0]+","+periods[0]+")"conn.query(sql)if (int(periods[0])-1)%100==0:conn.commit()except Exception as err:print (err)
conn.commit()
数据库查询数据量:
select count(*) from tb_dou_color
发现少了5条数据
筛选出遗漏的5条数据
先查出数据库已有的数据
sql1="select period from tb_dou_color"
#获取游标
cur=conn.cursor()
#执行查询
cur.execute(sql1)
#提取数据
rows=cur.fetchall()
将数据库提取到数据库封装到集合 arrs 中:
arrs=[]
for i in rows:print(i[0])arrs.append(i[0])
提取所有需要爬取的所有期数
arrays=[]
for i in res:patt="http://kaijiang.500.com/shtml/ssq/(.*?).shtml"print(i)ind=re.compile(patt).findall(i)b=int(ind[0])print(str(b))
将两个集合取差集,得到丢失了数据
div=list(set(array).difference(set(arrs)))
#['17001', '15081', '13091', '10119', '3069']
再次对丢失的数据爬取一次
for url in res:patt="http://kaijiang.500.com/shtml/ssq/(.*?).shtml"index=re.compile(patt).findall(url)if str(int(index[0])) not in div:continuetry:print(url)html=use_proxy(url,proxy_addr)try:decompressed_data = zlib.decompress(html ,zlib.MAX_WBITS|32)except Exception as err1:print (err1)try:decompressed_data = zlib.decompress(html ,zlib.MAX_WBITS|16)except Exception as err2:print (err2)try:decompressed_data = zlib.decompress(html)except Exception as err3:print(err3)decompressed_data = zlib.decompress(html,-zlib.MAX_WBITS)pattern1='<li class="ball_red">(.*?)</li>'pattern2='<li class="ball_blue">(.*?)</li>'pattern3='<font class="cfont2"><strong>(.*?)</strong>'pattern4='<span class="span_right">(.*?)</span>'reds=re.compile(pattern1).findall(str(decompressed_data))blues=re.compile(pattern2).findall(str(decompressed_data))periods=re.compile(pattern3).findall(str(decompressed_data))print(reds[0])print(blues[0])print(periods[0])sql="insert into tb_dou_color (red_one,red_two,red_three,red_four,red_five,red_six,blue,period) values ("+reds[0]+","+reds[1]+","+reds[2]+","+reds[3]+","+reds[4]+","+reds[5]+","+blues[0]+","+periods[0]+")"conn.query(sql)if (int(periods[0])-1)%100==0:conn.commit()except Exception as err:print (err)
conn.commit()
最后还剩一条网站丢失的数据,手动去查询其他网站,添加到数据库
(1064, "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '{Result2},{Result3},{Result4},{Result5},{Result6},,17001)' at line 1")
http://kaijiang.500.com/shtml/ssq/15081.shtml
182.108.44.47:808
至此,数据全部爬取完成
Ⅵ.数据处理分析
import pandas as pd
k=pd.read_sql("select * from tb_dou_color",conn)
df=k.describe()id red_one ... red_six blue
count 2415.000000 2415.000000 ... 2415.000000 2415.000000
mean 1594.991304 4.751553 ... 28.925052 8.649689
std 1219.295142 3.701862 ... 3.777546 4.617859
min 1.000000 1.000000 ... 11.000000 1.000000
25% 606.500000 2.000000 ... 27.000000 5.000000
50% 1210.000000 4.000000 ... 30.000000 9.000000
75% 2749.500000 7.000000 ... 32.000000 13.000000
max 4610.000000 24.000000 ... 33.000000 16.000000df.to_csv('e:/python/code/res1.csv',index=False,header=False)
利用excel处理csv文件,进行进一步概率分析,利用excel 的rank等函数处理,得到最终结果:
未经允许,切勿扩散,Thanks♪(・ω・)ノ
福利彩票-双色球爬虫数据分析实战相关推荐
- 爬虫数据分析实战——腾讯视频《奔跑吧》第九季弹幕数据分析
原文链接 淘宝搜券小助手上线啦,喜欢网购的你赶快来试试吧~!淘宝搜券微信机器人正在开发中,尽情期待!点击链接进入→淘宝搜券小助手 一.概述 1.数据来源 本次数据分析使用的数据来源腾讯视频的<奔 ...
- Python 爬虫和数据分析实战
课程介绍 本课程以一个小项目带你快速上手 Python 爬虫和数据分析,主要分 3 部分: 第 1 部分是 Python 爬虫,主要使用 Urllib 3 和 BeautifulSoup 抓取天猫商城 ...
- python爬虫的应用-python网络爬虫应用实战
原标题:python网络爬虫应用实战 Python这门编程语言包罗万象,可以说掌握了python,除了一些特殊环境和高度的性能要求,你可以用它做任何事. Python作为一门脚本语言,它灵活.易用.易 ...
- 爬虫技术实战 | WooYun知识库
爬虫技术实战 | WooYun知识库 爬虫技术实战 大数据分析与机器学习领域Python兵器谱-大数据邦-微头条(wtoutiao.com) 大数据分析与机器学习领域Python兵器谱
- Python_数据分析_关联规则和王者荣耀数据分析实战
如果同学不喜欢看理论,可以直接看后面王者数据分析的部分. 关联规则 如果不知道尿布和啤酒问题,建议百度百科,先有个大致的了解 我们找百度百科上面的例子来讲一下 tid是交易单号,后面每一纵列中1代表购 ...
- 数据分析实战----北京租房数据统计分析
2.1 数据分析实战----北京租房数据统计分析 学习目标 掌握 Pandas的读写操作 会使用预处理技术过滤数据. 会使用 Matplotlib库绘制各种图表. 会基于数据进行独立分析. 近年来随着 ...
- python基础实例教程 微课版-Python爬虫开发实战教程(微课版)
第1章 静态网页爬虫 1 1.1 爬虫的基本概念和工作原理 2 1.1.1 什么是网络爬虫 2 1.1.2 爬虫的结构与工作流程 3 1.2 爬虫抓包分析 4 1.2.1 使用Chrome浏览器进行抓 ...
- Python网络爬虫数据采集实战:Scrapy框架爬取QQ音乐存入MongoDB
通过前七章的学习,相信大家对整个爬虫有了一个比较全貌的了解 ,其中分别涉及四个案例:静态网页爬取.动态Ajax网页爬取.Selenium浏览器模拟爬取和Fillder今日头条app爬取,基本 ...
- bilibili爬虫+数据分析
Python爬虫+数据分析+数据可视化实战 Python爬虫+数据分析+数据可视化实战 1. 背景介绍 2. 需求目标 3. 基于urllib的bangumi和bilibili一键爬虫脚本的编写 3. ...
- 腾讯弹幕数据分析实战
腾讯弹幕数据分析实战 通用爬虫代码: 令人心动的offer2可视化分析 批量导入数据并合并 数据读取 数据处理及清洗 重命名 过滤字段 时间格式转换 机械压缩函数处理comment 会员等级打标 数据 ...
最新文章
- CStopWatch计时器的用法实例
- statistics DATA in jiangsu
- 台达plc控制伺服电机编程实例_PLC控制伺服电机:控制脉冲的相关计算
- DevExpress v18.1新版亮点——WPF篇(五)
- java 虚拟机 字节码,JAVA虚拟机:虚拟机字节码执行引擎
- WEB安全基础-PHP+MySQL实践
- java 图片上传_java web图片上传和文件上传实例
- 应用程序架构指导袖珍版
- hdfs 数据迁移_基于 JindoFS+OSS 构建高效数据湖
- Linux工作笔记024---Centos7 下查看本机公网IP
- LinkedList和 ArrayList的大数据面试资料(面试题)
- 使用 jQuery 和 KnockoutJS 开发在线股票走势图应用
- OpenCV python
- pikachu~~~验证码绕过(on client on server)
- 两轮电自2.0时代开启 小牛电动以独立主见创造新物种
- 如何搭建一个自己图床网站
- 【转载】VLOOKUP函数多条件查询 VLOOKUP三个条件查询
- 全量发布与灰度发布(APP版本发布)
- Java能够做哪些工作?这7个Java开发方向你知道几个?
- 【学习笔记】数据结构之单链表(先进先出、先进后出)