最近学习了一下Python的基础,想写个东西练练手。正好每次跟号的大乐透还需要手动兑奖或者去彩票站兑奖,自己写一个脚本自动抓取开奖结果,核对开奖金额后邮件通知。
整体思路:
- 找可抓取开奖结果网站
- 找可以发送邮件的免费服务器
- 写抓取、兑奖、发邮件脚本
- 设定自动执行脚本
踩坑:
- 2.7.3版本,使用requests、urllib3包的ssl有问题,最后也没解决了,执行的时候能执行,但是有警告信息,3.1上没问题。
- 找的网站,抓取历史数据的时候,频繁抓取会被限制,需要设定执行频率或者更改proxy。
详细过程:
1,找可抓取开奖结果网站
要求:开奖后及时更新结果;结果数据方便解析;
最后选中了彩经网的,开奖半小时内更新,而且结果只有一个table,很简单,方便解析。
例:https://www.cjcp.com.cn/kaijiang/data/ajax_dlt.php?qh=2021146
2,找免费发送的邮件服务器
要求:常用QQ邮箱,那些非互联网上认证的邮件发送服务器(域名和出口IP不一致)的邮件会被拒收,所以需要找一个互联网上认证的邮件服务器进行发送。横向比较后,选择了163邮箱(比QQ邮箱认证简单一些)。
3,写抓取、兑奖、发邮件脚本
抓取:
#从彩经网获取大乐透开奖号码, #lot:彩票期数,例如:2021140 def getlottery(lot): target = "https://www.cjcp.com.cn/kaijiang/data/ajax_dlt.php?qh=" + lot #设置requests header headers={ 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36', 'Host': 'www.cjcp.com.cn', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3' } req = requests.get(url=target,headers=headers,verify=False) #req = requests.get(url=target,verify=False) #print(req.text) red = [] #blue = [] num="" #txt=(BS(req.text,'lxml')).splitlines() txt=req.text.splitlines() for ln in txt: if "qiu_r" in ln: num = ln.replace('',"").replace("","").strip() #print(num) # red += num red.append(num) elif "qiu_b" in ln: #print(ln) num = ln.replace('',"").replace("","").strip() #print(num) #blue += ln.replace('',"").replace("","") red.append(num) return red
核对:
#查看是否中奖 #buy_num:买的号码,单注形式 例如:04,08,14,33,35:06,10 #prize_num:开奖号码,例如:03, 20, 25, 30, 34, 02, 09] #return:中几等奖,0:未中奖,1-9中的奖的等数 def checkprized(buy_num,prize_num): prized = '0' #开奖红球 pred = prize_num[0:5] #开奖蓝球 pblue = prize_num[5:7] #购买红球 br = buy_num.split(':')[0] #购买蓝球 bb = buy_num.split(':')[1] #print('bought:',br,':::',bb) rcnt = 0 bcnt = 0 #红球匹配数 for num in br.split(','): if num in pred: rcnt += 1 #蓝球匹配数 for num in bb.split(','): if num in pblue: bcnt += 1 #中奖规则 if rcnt == 5 and bcnt == 2: prized = '1' elif rcnt == 5 and bcnt == 1: prized = '2' elif rcnt == 5 and bcnt == 0: prized = '3' elif rcnt == 4 and bcnt == 2: prized = '4' elif rcnt == 4 and bcnt == 1: prized = '5' elif rcnt == 3 and bcnt == 2: prized = '6' elif rcnt == 4 and bcnt == 0: prized = '7' elif (rcnt == 3 and bcnt == 1) or (rcnt == 2 and bcnt == 2): prized = '8' elif rcnt == 3 or (bcnt == 1 and rcnt ==2) or (bcnt == 2 and rcnt ==1) or bcnt == 2: prized = '9' else: prized = '0' return prized
计算金额:
#根据中几等奖计算中奖金额 #prized:中几等奖 #return:中奖金额,1,2等奖浮动按照1千万和2百万计算 def countpay(prized): pay = 0 for i in prized: if i == '0': continue elif i == '1': pay += 10000000 elif i == '2': pay += 2000000 elif i == '3': pay += 10000 elif i == '4': pay += 3000 elif i == '5': pay += 300 elif i == '6': pay += 200 elif i == '7': pay += 100 elif i == '8': pay += 15 elif i == '9': pay += 5 #print "中奖金额:" + str(pay) return pay
发送邮件
def send(subject,content,receivers=['xxxxxxxx@qq.com']): #设置服务器所需信息,使用163邮箱发送 #邮箱服务器地址 mail_host = 'smtp.163.com' #用户名 mail_user = 'xxxxxxxx' #密码(部分邮箱为授权码) mail_pass = 'xxxxxxxx' #邮件发送方邮箱地址 sender = 'xxxxxxxx@163.com' #邮件接受方邮箱地址,注意需要[]包裹,这意味着你可以写多个邮件地址群发 #receivers = ['xxxxxxxx@qq.com'] #设置email信息 #邮件内容设置 message = MIMEText(content,'plain','utf-8') #邮件主题 message['Subject'] = subject #发送方信息 message['From'] = sender #接受方信息 message['To'] = receivers[0] #登录并发送邮件 try: smtpObj = smtplib.SMTP() #连接到服务器 smtpObj.connect(mail_host,25) #登录到服务器 smtpObj.login(mail_user,mail_pass) #发送 smtpObj.sendmail(sender,receivers,message.as_string()) #退出 smtpObj.quit() except smtplib.SMTPException as e: print('error',e) #打印错误 #send('测试邮件','测试内容')
主程序
#主程序开始 #从lotfile中取上次写入的期数数 lot = "2021140" with open('lotfile', 'r') as f: for l in f: lot = l.strip('n') break f.close() #取系统时间的年份 year = time.strftime("%Y", time.localtime()) #判断年份是否和lot的年份一致,不一致设为为当年第一期 if lot[0:4] != year: lot = year + '001' #从采经网获取开奖号码 #num = ['03','04','21','22','35','02','09'] num = getlottery(lot) #没有取得开奖结果(非未开奖) if not num: print('系统或网络问题') sys.exit(1) elif num[0] == '': #未开奖的时候,有报文,没有中奖号码 print('尚未开奖') sys.exit(0) #是否中奖,针对购买号码的组数,序列类型 isprized=[] #邮件内容 content='' #从bought文件中读取购买号码,可以放多条,每条一行 #按照单式记录,格式为1,2,3,4,5:6,7 with open('bought', 'r') as fb: for l in fb: lt = l.strip('n').strip() #如果有空行的话略过 if len(lt) ==0: continue #每行验证是否中奖 isprized += checkprized(lt,num) #将所购号码放入邮件内容中 content += l + 'n' fb.close #计算中奖金额 #isprized=['1','2','5','6','9'] #print('isprized:',isprized) #print countpay(isprized) pay = countpay(isprized) #邮件标题 subject='' + lot + ':' + ','.join(num) + ':' + str(pay) #print(subject) #如果已开奖记录结果,并发送邮件,如果为空则为未开奖,什么都不做 #将开奖结果记入年份的文件,留作记录 with open(year, 'a+') as rf: rf.write(subject + 'n') rf.close() #将下一期的期数,放到lotfile中 with open('lotfile', 'w') as lf: lf.write(str(int(lot)+1)) lf.close() #发送邮件,标题,内容;收件人使用默认的 send(subject,content)
4,定时执行
扔在云上的Linux服务器上,设定Crontab
crontab -u python -e 0 21 * * * /opt/sh/check_everyday.py
完整代码稍后上传。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)