众所周知,填了体温就不会感染新冠。但是早晚各一次的体温填报实在太过于麻烦。我的想法是体温正常时程序会自动上报体温。
出于懒惰,写了一个python程序解决这个问题,
还是处于懒惰,又换用了实现方法实施无界面填报,
可还想在懒一些,所以把程序函数化,丢到免费的云函数服务器上。
| 版本 | 升级动力 |
|---|---|
| 本地版 | 填个体温还要开电脑,麻烦 |
| 云电脑版 | 一年服务器少说要一张毛爷爷,浪费钱 |
| 云函数版 | 省心省事,够用了,不升级了做优化 |
import requests # 爬虫模块,本程序的根本。 import time #获取时间模块,可能需考虑时区。 import json #解析服务器数据,修改格式串 import random #生成随机数模块,生成随机体温 from lxml import etree # from…import * 爬虫?还是数据解析来着,忘记了 from requests.packages.urllib3.exceptions import InsecureRequestWarning # 最后一行用于修复代理的问题,如果没有会报错。下面定义 全局变量。具体的含义看注释
如果需要填写自己的体温,将user1换成自己的学号,pw1换成md5密码
dict_text = [] # 创建一个空字典用于存储推送内容
classnums = ['user1', 'user2', 'user3'] #填写学号
passages = [
('pwd1'),('pwd2'),('pwd3'),
]
sckey = "你的sckey推送码" # Server酱推送提醒,需要填写sckey,官网:https://sc.ftqq.com/3.version
# 由于云服务器时间有问题,所有在这里进行修正。具体根据服务器确定
now = int(time.time()+28800) # 通过时间戳做出时间修正 28800=八小时
timeArray = time.localtime(now) # 转换为其他日期格式,如:"%Y-%m-%d %H:%M:%S"
下面定义 随机体温函数。
def rands(): # 随机数模块,实现范围内的随机体温,不建议修改此项
temp = '{:.1f}'.format(random.uniform(35.9, 36.4))
print("当前生成的体温是" + temp)
return temp # 相当于 赋值temp=rands()
下面定义 打印输出(调试函数)与追加字典函数。
def pr1(n): # 打印函数,实现输出打印内容的同时追加字典
get_dict0 = n
get_dict1 = "##### " + n
print("get_dict0是" + get_dict0)
dict_text.append(get_dict1)
下面定义 推送函数。
def pushwechat(b): # 推送函数
scurl = f"https://sctapi.ftqq.com/{sckey}.send"
param = {
'title': '体温填报提醒', #推送标题
'desp': b #推送内容
}
requests.post(scurl, params=param)
下面定义 填报函数。
获取 当前时间。
time_tbsj = time.strftime("%Y-%m-%d %H:%M", timeArray) #输出:年-月-日,小时:分钟
n = "今天是" + time_tbsj
pr1(n) #追加内容,日期
构造 循环体头。
# 构造循环体,方便同时填报多人体温
for i in range(0, len(classnums), 1): # 根据用户数自动选择循环次数
classnum = classnums[i]
passage = passages[i]
get_dict = {
'username': classnum,
'password': passage
}
构造 循环体提醒。
n = "========正在填报" + get_dict['username'] + "同学的体温========"
pr1(n)
tem_tj = rands() # 要提交的体温值
构造 循环体第一步---获取登录参数。
# 第一步:获取一个关键值execution,供登陆时使用
url1 = ("https://web-vpn.sues.edu.cn/https/77726476706e69737468656265737421f3f652d234256d43300d8db9d6562d/cas/"
"login?service=https%3A%2F%2Fweb-vpn.sues.edu.cn%2Flogin%3Fcas_login%3Dtrue") # 登录网址 # 代码过长用()连接
z1 = requests.get(url1)
z1.encoding = 'utf-8'
# print(z1.text) # 打印网页源码,查看是否成功获取到界面
content = etree.HTML(z1.text) # 便于使用下面的Xpath
execution = content.xpath('//input[@name="execution"]/@value')[0]
# print("获得一个登录时需要的execution为:" + execution) # 获得到需要的execution
构造 循环体第二步---登录网页。
# 第二步:模拟登入网页VPN
url2 = ("https://web-vpn.sues.edu.cn/https/77726476706e69737468656265737421f3f652d234256d43300d8db9d6562d/cas/"
"login?service=https%3A%2F%2Fweb-vpn.sues.edu.cn%2Flogin%3Fcas_login%3Dtrue")
headers2 = {
"User-Agent": ("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) C"
"hrome/91.0.4472.164 Safari/537.36 Edg/91.0.864.71"),
"Referer": (
"https://web-vpn.sues.edu.cn/https/77726476706e69737468656265737421f3f652d234256d43300d8db9d6562d/cas/"
"login?service=https%3A%2F%2Fweb-vpn.sues.edu.cn%2Flogin%3Fcas_login%3Dtrue")
}
data2 = {
"username": get_dict['username'],
"password": get_dict['password'],
"execution": execution, # 登录参数,没有这个参数会登录失败
"encrypted": "true",
"_eventId": "submit",
"loginType": "1", # 登录类型,对于本科生1就好
"submit": "登 录"
}
requests.packages.urllib3.disable_warnings(InsecureRequestWarning) # 用于修复证书安全校验
session = requests.session() # 保持登录操作,懒得使用cookie了
z2 = session.post(url=url2, headers=headers2, data=data2, verify=False, timeout=(3, 7))
构造 循环体第三步---判断是否登录成功。
# 判断是否登录成功,这一步理论上是多余的,但是能跑起来的程序就不要修BUG
url3 = ("https://web-vpn.sues.edu.cn/https/77726476706e69737468656265737421e7f8539"
"7213c6747301b9ca98b1b26312700d3d1/default/work/shgcd/jkxxcj/jkxxcj.jsp")
z3 = session.post(url=url3, verify=False, timeout=(3, 7))
print("该同学的体温填写界面的状态码为:" + str(z3.status_code))
# 获得z3的响应值,200代表成功
# 可以通过打印源代码来判断是否登录成功
构造 循环体第四步---获取当前时间及时段。
# 第四步 获取变量数据(提交时间)同时判断当前时段
time_tjsj1 = time.strftime("%Y-%m-%d %H:%M", timeArray) #
time_tjsj0 = time.strftime("%Y-%m-%d", timeArray)
tjsj1 = time.strftime("%H", timeArray)
print("time_tjsj1:现在是" + time_tjsj1)
# print("time_tjsj0:今天是" + time_tjsj0)
# print("tjsj1:当前为" + tjsj1 + "时")
if int(tjsj1) > 11:
sd = "下午"
else:
sd = "上午"
print("当前时段为:" + sd) # 获得时间的KET并打印time_key判断是否正确
time_key = time.strftime("%Y-%m-%d %H:%M", timeArray)
构造 循环体第五步---获取除体温外的参数()。
# 第五步 获得ID参数等值(同第二步)
time.sleep(2)
url5 = ("https://web-vpn.sues.edu.cn/https/77726476706e69737468656265737421e7f85397213c6747301b9ca98b1b263127"
"00d3d1/default/work/shgcd/jkxxcj/com.sudytech.work.shgcd.jkxxcj.jkxxcj.queryNear.biz.ext?vpn-12-o2-"
"workflow.sues.edu.cn") # 很重要,通过这个界面获得ID等参数
headers5 = {
"User-Agent": ("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) C"
"hrome/91.0.4472.164 Safari/537.36 Edg/91.0.864.71"),
"Referer": ("https://web-vpn.sues.edu.cn/https/77726476706e69737468656265737421e7f85397213c6747301b9ca98b1b"
"26312700d3d1/default/work/shgcd/jkxxcj/jkxxcj.jsp"),
"Content-Type": "text/json",
}
z5 = session.post(url=url5, headers=headers5, verify=False, timeout=(3, 7)) #data=json.dumps(data5),
j5 = z5.json()
# 解析服务器数据,提取有用的值
ID = j5["resultData"][0]['ID']
SQRID = j5["resultData"][0]['SQRID']
SQBMID = j5["resultData"][0]['SQBMID']
RYSF = j5["resultData"][0]['RYSF']
SQRMC = j5["resultData"][0]['SQRMC']
SFZH = j5["resultData"][0]['SFZH']
SQBMMC = j5["resultData"][0]['SQBMMC']
XB = j5["resultData"][0]['XB']
LXDH = j5["resultData"][0]['LXDH']
NL = j5["resultData"][0]['NL']
XRYWZ = j5["resultData"][0]['XRYWZ']
XQ = j5["resultData"][0]['XQ']
SHENG = j5["resultData"][0]['SHENG']
SHI = j5["resultData"][0]['SHI']
QU = j5["resultData"][0]['QU']
JTDZINPUT = j5["resultData"][0]['JTDZINPUT']
JKZK = j5["resultData"][0]['JKZK']
JKQK = j5["resultData"][0]['JKQK']
print(get_dict['username'] + "同学的当前填报的唯一ID是:" + str(ID)) #用于调试程序
构造 循环体第六步---构造数据包,发包。
# 第六步 发送体温包(同第二步)
url6 = ("https://web-vpn.sues.edu.cn/https/77726476706e69737468656265737421e7f85397213c6747301b9ca98b1b26312700d3"
"d1/default/work/shgcd/jkxxcj/com.sudytech.work.shgcd.jkxxcj.jkxxcj.saveOrUpdate.biz.ext?vpn-12-o"
"2-workflow.sues.edu.cn")
headers6 = {
"User-Agent": ("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) C"
"hrome/91.0.4472.164 Safari/537.36 Edg/91.0.864.71"),
"Referer": ("https://web-vpn.sues.edu.cn/https/77726476706e69737468656265737421e7f85397213c6747301b9ca9"
"8b1b26312700d3d1/default/work/shgcd/jkxxcj/jkxxcj.jsp"),
"Content-Type": "text/json",
}
# 构造数据包
data6 = {
"params": {
"id": ID,
"sqrid": SQRID,
"sqbmid": SQBMID,
"rysf": RYSF,
"sqrmc": SQRMC,
"gh": get_dict['username'],
"sfzh": SFZH,
"sqbmmc": SQBMMC,
"xb": XB,
"lxdh": LXDH,
"nl": NL,
"tjsj": time_tjsj1,
"xrywz": XRYWZ,
"xq": XQ,
"sheng": SHENG,
"shi": SHI,
"qu": QU,
"jtdzinput": JTDZINPUT,
"gj": "",
"jtgj": "",
"jkzk": JKZK,
"jkqk": JKQK,
"tw": tem_tj,
"sd": sd,
"bz": "",
"_ext": "{}"
}
}
z6 = session.post(url=url6, headers=headers6, data=json.dumps(data6), verify=False, timeout=(3, 7))
print(str(z6.text)) # 调试程序
# 判断体温是否填报成功
if z6.text == "{"result":{"code":"","errorcode":"0","msg":"","success":true}}": #小变动,code不含200
n = get_dict['username'] + "体温填写成功,今天填报的体温是" + str(tem_tj) + "摄氏度。"=-
pr1(n)
else:
n = get_dict['username'] + "填写失败,请手动填报"
pr1(n)
time.sleep(5)
构造 推送体。
print("体温填报结束,按回车退出nnn")
print("以下是推送文章的内容n" + str(dict_text))
b = ""
for add in dict_text:
b = b + str(add) + "nn"
#print("b是:" + b)
pushwechat(b)
return
构造 入口函数。
def main(event, content): #体温填报的函数入口 上云的时候使用
tianbao()
思考
- 这个体温填报不是很安全(比如个人信息都是明文),但是正是因为这种不安全才有这个程序。不然还要学解密麻烦。
- 整体思路比较简单,反复套用基本的爬虫语句。导致代码行数过多。
-------------------程序设计进度进度----------------
- 判断体温是否已经填写,如果已填写则跳过。
- 加入数据读取模块,优化代码行数
- 日志本地化保存
- 未完待续~
- V2.4 日常维护(测试版)
- V2.3 修复重大BUG(测试版)
- V2.2 重启程序,去除填报体温功能,仅为提醒程序
- V2.1 未知BUG导致填报失效,无法修复,为返校暂停程序
- V2.0 代码上云,实现定时填报
- V1.4 优化代码,将所需修改的变量至于程序头,便于阅读
- v1.3 支持填报任意人数的体温
- V1.2 支持填报一定人数的体温
- V1.1 优化程序:去除填报窗口界面
- V1.0 基本功能:填报体温



