21 点的主页面
- https://---
- (此处不提供链接, 用户直接在网站首页点击 21 点后, 地址栏的链接便是.)
需要知道的关键点
(写代码时用来抓取数据的关键点)
1. 等待开局
若之前的 21 点还没有结束 (暂时没有对手上线), 那么不能开局, 需等待之前的结束. 若需等待, 主页面包含以下内容
<button type="submit" class="btn btn-default"> 刷新 </button>
2. 可以开始
若可以开始游戏, 主页面包含以下内容
<button type="submit" class="btn btn-primary"> 开始游戏!</button>
3. 开始 21 点
向主页面 post 数据
- game: hit,
- start: yes
4. 判断点数
判断每次操作后, 主页面返回的网页内容. 点数的 html 样式如下:
<b > 点数 = 16</b>
5. 继续摸牌
向主页面 post 数据
game: hit
6. 停止摸牌
向主页面 post 数据
game: stop
Python 脚本思路
等待开局.
开始 21 点.
判断点数.
若点数大于 20, 回到第 1 步.
若点数大于 17, 则去到第 8 步.(17 可变, 只是我认为 17 点够大了)
若点数小于等于 17, 则去到第 7 步.
继续摸牌, 回到第 3 步.
停止摸牌, 回到第 1 步.
toulanboy - http://www.cnblogs.com/toulanboy/
代码实现
1. 关键逻辑: 开始 - 摸牌 - 停止
- #(** 此处不提供链接, 用户直接在网站首页点击 21 点后, 地址栏的链接便是.**)
- url = 'https://----'
- # 不停地玩 21 点
- while True:
- #先看之前的是否结束了
- result = getData(url)
- time.sleep(5) # toulanboy - http://www.cnblogs.com/toulanboy/
- if result == 0: #如果还没结束, 则继续刷新
- print "之前的尚没结束, 等待中"
- elif result == 1:# 如果结束了, 则开始游戏
- point = postData(url, startValues)# 发出 "开始游戏" 请求
- print "已开局, 当前点数 = %d" % point
- #大于 20 点, 系统会自动结束, 故在这里我只需在小于 21 点的情况下摸牌
- while point <= 20:
- if point>= 17:# 我认为只要大于 17 点我满足了, 所以大于 17 点就停止摸牌
- time.sleep(1)
- postData(url, stopValues)# 发出 "停止摸牌" 请求
- print "停止摸牌了, 当前点数 = %d" % point
- break
- else:# 小于 17 点则继续摸牌
- time.sleep(1)
- point = postData(url, hitValues)# 发出 "继续摸牌" 请求
- print "又摸牌了, 当前点数 = %d" % point
- print "这局结束了, 当前点数 = %d" % point
- else:# 出现异常, 则停止游戏. 等待渣渣看日志看看哪里出问题了.
- sendEmail("xxx@qq.com", "Some errors occurred in python script for npubits", "Some errors occurred in python script for npubits")
- break
2. 用 get 请求判断是否可以开始游戏
- #function - Get 网页
- # 若网页显示之前的没结束, 则返回 0
- # 若网页显示可以开始新的一局, 则返回 1
- # 其它情况返回 - 1
- def getData(url):
- headers = {
- 'User-Agent' : '-',# 建议设置
- 'cookie':'-'# 我没做登陆, 所以手动弄 cookie
- }
- try:
- response = requests.get(url, headers=headers)
- indexHtmlCode = response.text
- indexHtmlCode = indexHtmlCode.encode('utf-8')
- #判断是否有刷新按钮, 若有, 说明上局没结束
- freshRegex = r'刷新 </button>'
- result = re.findall(freshRegex, indexHtmlCode)
- if result:
- return 0
- # toulanboy - http://www.cnblogs.com/toulanboy/
- #判断是否有开始游戏按钮, 若有, 说明可以开始游戏
- beginRegex = r'开始游戏!</button>'
- result = re.findall(beginRegex, indexHtmlCode)
- if result:
- return 1
- return -1
- except Exception as e:
- return -1
3. 用 Post 请求实现开始 / 摸牌 / 停止的动作
- toulanboy - http://www.cnblogs.com/toulanboy/
- ### 不同动作需要的数据不一样
- # 开始游戏
- startValues = {
- "game":"hit",
- "start":"yes"
- }
- # 继续摸牌
- hitValues = {
- "game":"hit"
- }
- # 停止摸牌
- stopValues = {
- "game":"stop"
- }
- #function - Post 网页
- # 若是开始和摸牌, 则返回点数
- # 页面没有点数 (停止摸牌操作会出现), 则返回 0
- # 异常, 返回 - 1
- def postData(url, values):
- dd = urllib.urlencode(values)
- headers = {
- "Content-Length":str(len(dd)),
- "Content-Type":"application/x-www-form-urlencoded",
- 'Cache-Control':'max-age=0',# 上述三个参数其实应该不用手动添加, 有可能 request 库会帮我们添加. 有待验证.
- 'User-Agent' : '-',# 自己补充
- 'cookie':'-'# 自己补充
- }
- try:
- response = requests.post(url, data=dd,headers=headers)
- indexHtmlCode = response.text
- indexHtmlCode = indexHtmlCode.encode('utf-8')
- # toulanboy - http://www.cnblogs.com/toulanboy/
- # 查看返回的网页的点数
- pointRegex = r'点数 \ s?=\s?(\d*)<'
- result = re.findall(pointRegex, indexHtmlCode)
- if result:
- return int(result[0])
- else:
- return 0
- except Exception as e:
- return -1
完整代码
为了便于维护, 完整代码中增加了日志记录和邮件提醒
- #!/usr/bin/python
- # coding=utf-8
- # 时间: 2018-08-22
- # 作者: toulanboy
- # 缘由: 想实现自动玩 npubits 的 21 点游戏
- import requests
- import re
- import urllib
- import time
- import logging
- import smtplib
- from email.mime.text import MIMEText
- # 配置日志
- logging.basicConfig(filename='my.log',format='[%(asctime)s-%(filename)s-%(levelname)s:%(message)s]', level = logging.INFO,filemode='a',datefmt='%Y-%m-%d %I:%M:%S %p')
- ### 不同动作需要的数据不一样
- # 开始游戏
- startValues = {
- "game":"hit",
- "start":"yes"
- }
- # 继续摸牌
- hitValues = {
- "game":"hit"
- }
- # 停止摸牌
- stopValues = {
- "game":"stop"
- }
- # toulanboy - http://www.cnblogs.com/toulanboy/
- #function - Post 网页
- # 若是开始和摸牌, 则返回点数
- # 页面没有点数 (停止摸牌操作会出现), 则返回 0
- # 异常, 返回 - 1
- def postData(url, values):
- dd = urllib.urlencode(values)
- headers = {
- "Content-Length":str(len(dd)),
- "Content-Type":"application/x-www-form-urlencoded",
- 'Cache-Control':'max-age=0',# 上述三个参数其实应该不用手动添加, 有可能 request 库会帮我们添加. 有待验证.
- 'User-Agent' : '-',# 自己补充
- 'cookie':'-'# 自己补充
- }
- try:
- response = requests.post(url, data=dd,headers=headers)
- indexHtmlCode = response.text
- indexHtmlCode = indexHtmlCode.encode('utf-8')
- # 提取网页主干, 存入日志 (方便后期的分析)
- body = re.findall(r'<div\s?id=\'main\'\s?class=\'well\s?no-border-radius\'>.*?</div>',indexHtmlCode, re.S)
- if body:
- logging.info(body[0])
- else:
- logging.info(indexHtmlCode)
- # 查看返回的网页的点数
- pointRegex = r'点数 \ s?=\s?(\d*)<'
- result = re.findall(pointRegex, indexHtmlCode)
- if result:
- return int(result[0])
- else:
- return 0
- except Exception as e:
- logging.error(e)
- return -1
- #function - Get 网页
- # 若网页显示之前的没结束, 则返回 0
- # 若网页显示可以开始新的一局, 则返回 1
- # 其它情况返回 - 1
- def getData(url):
- headers = {
- 'User-Agent' : '-',# 建议设置
- 'cookie':'-'# 我没做登陆, 所以手动弄 cookie
- }
- try:
- response = requests.get(url, headers=headers)
- indexHtmlCode = response.text
- indexHtmlCode = indexHtmlCode.encode('utf-8')
- #判断是否有刷新按钮, 若有, 说明上局没结束
- freshRegex = r'刷新 </button>'
- result = re.findall(freshRegex, indexHtmlCode)
- if result:
- return 0
- #判断是否有开始游戏按钮, 若有, 说明可以开始游戏
- beginRegex = r'开始游戏!</button>'
- result = re.findall(beginRegex, indexHtmlCode)
- if result:
- return 1
- # 若以上情况都不是, 有可能是 cookie 过期了
- loginRegex = r'您尚未登录 </body>'
- result = re.findall(loginRegex, indexHtmlCode)
- if result:
- return 2
- # 如果不是 cookie 过期, 则需打印当前错误信息 (记录返回的网页源代码), 方便后面找错
- logging.error(indexHtmlCode)
- except Exception as e:
- logging.error(e)
- return -1
- # 发邮件 (收件人 , 邮件主题 , 邮件正文)
- def sendEmail(_to, subject, mainText):
- _user = "-" #登录的 163 邮箱
- _pwd = "-" #163 邮箱授权码
- msg = MIMEText(mainText) #邮件正文
- msg["Subject"] = subject #邮件主题
- msg["From"] = _user #发件人
- msg["To"] = _to #收件人
- try:
- s = smtplib.SMTP_SSL("smtp.163.com", 465)
- s.login(_user, _pwd)# 登录
- s.sendmail(_user, _to, msg.as_string())# 发送
- s.quit()# 退出登录
- logging.info("邮件发送成功!")
- print "邮件发送成功!"
- except smtplib.SMTPException,e:
- logging.info("邮件发送失败,%s"%e[0])
- print "邮件发送失败,%s"%e[0]
- #(** 此处不提供链接, 用户直接在网站首页点击 21 点后, 地址栏的链接便是.**)
- url = 'https://----'
- # 不停地玩 21 点
- while True:
- #先看之前的是否结束了
- result = getData(url)
- time.sleep(5)
- if result == 0: #如果还没结束, 则继续刷新
- print "之前的尚没结束, 等待中"
- elif result == 1:# 如果结束了, 则开始游戏
- point = postData(url, startValues)# 发出 "开始游戏" 请求
- logging.info("已开局, 当前点数 = %d" % point)
- print "已开局, 当前点数 = %d" % point
- #大于 20 点, 系统会自动结束, 故在这里我只需在小于 21 点的情况下摸牌
- while point <= 20:
- if point>= 17:# 我认为只要大于 17 点我满足了, 所以大于 17 点就停止摸牌
- time.sleep(1)
- postData(url, stopValues)# 发出 "停止摸牌" 请求
- logging.info("停止摸牌了, 当前点数 = %d" % point)
- print "停止摸牌了, 当前点数 = %d" % point
- break
- else:# 小于 17 点则继续摸牌
- time.sleep(1)
- point = postData(url, hitValues)# 发出 "继续摸牌" 请求
- logging.info("又摸牌了, 当前点数 = %d" % point)
- print "又摸牌了, 当前点数 = %d" % point
- logging.info("这局结束了, 当前点数 = %d" % point)
- print "这局结束了, 当前点数 = %d" % point
- else:# 出现异常, 则停止游戏. 等待渣渣看日志看看哪里出问题了.
- sendEmail("xxx@qq.com", "Some errors occurred in python script for npubits", "Some errors occurred in python script for npubits")
- break
- toulanboy - http://www.cnblogs.com/toulanboy/
完毕. python 刚刚学到点皮毛, 代码习惯可能不好, 希望大佬多多包涵.
如若有大佬愿意指点, 非常感谢.
来源: https://www.cnblogs.com/toulanboy/p/9522848.html