一、概述
python脚本不是我写的,源项项目地址(感谢作者的开源):
链接: https://github.com/Bmaili/NEU_health_daka
需要技术,简单的抓包,python的 re request模块
源项目是一个项目,有配置文件部分、发送邮件部分,我这里做了修改只保留了核心程序run.py部分,并且temperatureDaka函数不调用
import re
import time
import requests
#import sendMsg
#import config
#运行命令,cmd下
#python ./run.py 学号 校园网密码
import sys
class daka():
def __init__(self):
#self.id = config.stutendID
#self.password = config.passward
self.id = sys.argv[1]
self.password = sys.argv[2]
self.token = ""
self.name = ""
self.lt = ""
self.my_session = requests.session()
#self.sendMsg=sendMsg.sendMsg()
self.login_url = 'https://e-report.neu.edu.cn/login'
self.post_url = 'https://pass.neu.edu.cn/tpass/login'
self.create_url = 'https://e-report.neu.edu.cn/notes/create'
self.note_url = 'https://e-report.neu.edu.cn/api/notes'
def login(self):
#登陆,更新session
msg=''
try:
login_response = self.my_session.get(self.login_url)
self.lt = re.findall(r'LT-[0-9]*-[0-9a-zA-Z]*-tpass', login_response.text, re.S)[0]
login_form_items = {
'rsa': self.id + self.password + self.lt,
'ul': str(len(self.id)),
'pl': str(len(self.password)),
'lt': self.lt,
'execution': 'e1s1',
'_eventId': 'submit'
}
post_response = self.my_session.post(self.post_url, login_form_items)
msg=self.id+'登录成功!'
#print("登陆成功!")
#print("login success")
print(1200)#返回的第一个数据,登陆成功
except:
msg=self.id+'登录失败!请手动完成打卡!'
#print("登陆失败!")
#print("login fail")
print(1500)#返回的第一个数据,登陆失败
return msg
def healthDaka(self):
#健康打卡
msg=''
success=False
try:
note_response = self.my_session.get(self.create_url)
self.token = re.findall(r'name=\"_token\"\s+value=\"([0-9a-zA-Z]+)\"',note_response.text, re.S)[0]
self.name = re.findall(r'当前用户:\s*(\w+)\s*', note_response.text, re.S)[0]
health_items = {
'_token': self.token,
'jibenxinxi_shifoubenrenshangbao': '1',
'profile[xuegonghao]': self.id,
'profile[xingming]': self.name,
'profile[suoshubanji]': '',
'jiankangxinxi_muqianshentizhuangkuang': '正常',
'xingchengxinxi_weizhishifouyoubianhua': '0',
'cross_city': '无',
'qitashixiang_qitaxuyaoshuomingdeshixiang': ''
}
health_response = self.my_session.post(self.note_url, health_items)
if health_response.status_code == 201:
#print(str(health_response) + '健康打卡成功')
#msg=config.stutendID+'健康打卡成功!'
#msg=config.stutendID+'健康打卡成功!'
#print(str(health_response) + 'task success')
print(2200)#返回的第二个数据,打卡成功
#msg=config.stutendID+'健康打卡成功!'
msg=self.id+'task success'
success=True
else:
print(2500)#返回的第二个数据,打卡失败
msg=self.id+'健康打卡失败!请手动完成打卡!'+ '(响应异常)'+str(health_response)
except:
msg=self.id+'健康打卡失败!请手动完成打卡!'+ '(执行异常)'
return msg,success
def temperatureDaka(self):
#体温打卡
msg=''
success=False
try:
#hour = (time.localtime().tm_hour + 8) % 24 # 加8是因为腾讯云跑出来是格林时间,若是运行在自己服务器上需要改回来~
hour = (time.localtime().tm_hour ) % 24 # 加8是因为腾讯云跑出来是格林时间,若是运行在自己服务器上需要改回来~
temperature_url = 'https://e-report.neu.edu.cn/inspection/items/{}/records'.format(('1' if 7 <= hour <= 9 else '2' if 12 <= hour <= 14 else '3'))
temperature_items = {
'_token': self.token,
'temperature': '36.5',
'suspicious_respiratory_symptoms': '0',
'symptom_descriptions': ''
}
temperature_response = self.my_session.post(temperature_url, temperature_items)
if temperature_response.status_code == 200:
#print(str(temperature_response) + '体温打卡成功')
#msg=config.stutendID+'体温打卡成功!'
print(str(temperature_response) + 'temperature success')
msg=self.id+'temperature success'
success=True
else:
msg=self.id+'体温打卡失败!请手动完成打卡!'+ '(响应异常)'+str(temperature_response)
except:
msg=self.id+'体温打卡失败!请手动完成打卡!'+ '(执行异常)'
return msg,success
def main_handler(event, context):
_daka = daka()
loginMsg = _daka.login()
healthMsg, healSuc = _daka.healthDaka()
#temperatureMsg, tempSuc = _daka.temperatureDaka()
#早中晚体温打卡暂时就不做了
#if config.sendMsgOnlyError and healSuc and tempSuc:
# pass
#else:
# _daka.sendMsg.sendMessage(time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())+'\n'+loginMsg+'\n'+healthMsg+'\n'+temperatureMsg)
if __name__ == '__main__':
main_handler(None,None)
依赖库:requests
执行方法:
python ./run.py 学号 密码
二、抓包分析
写脚本应该是一个逆向的过程这里我们也逆向进行解析
为了教学,特意改了密码
账号:20206041
密码:mima123456
通过以下界面登录
看这张图,我们可以看到登陆页面是向
https://portal.neu.edu.cn/desktop/api/sso/login
提交数据
rsa:学号+密码+未知字符串(姑且叫他流水号)
ul:id的长度
pl:密码的长度
it:流水号
除了流水号以外其他的数据我们都可以直接提交
从python脚本来看,流水号保存在登陆界面
就是https://portal.neu.edu.cn/desktop/api/sso/login这个页面的数据
我们去看一眼登陆界面的数据,果然找到了他
刚好一样(这个不好找,在浏览器的控制台也许能好找)
注意提交数据我看的是webforms
返回数据看的是raw
登陆问题解决
下面看提交页面都提交了哪些数据,从以下页面打卡
提交数据并抓包
'_token': 未知字符串(这个不知道),
'jibenxinxi_shifoubenrenshangbao': '1',
'profile[xuegonghao]': 学号(这个执行脚本的时候就知道了),
'profile[xingming]': 姓名(这个不知道),
'profile[suoshubanji]': '',
'jiankangxinxi_muqianshentizhuangkuang': '正常',
'xingchengxinxi_weizhishifouyoubianhua': '0',
'cross_city': '无',
'qitashixiang_qitaxuyaoshuomingdeshixiang': ''
下面就是找到_token值和姓名
也是从上一界面查找(提交界面)
至此所有所需数据已经分析完毕,编写脚本
三、脚本编写
实现细则不做讨论(正则表达式提取部分),说一下大致逻辑
代码21行
requests.session()是为了保持cookie
跨请求保持某些参数,在同一个session实例发出的所有请求之间保持cookies
代码34、35行
来到登陆页面
从返回数据中提取下一步登录所需的流水号
代码63、64、65
来到健康上报页面,获取所需的_token和姓名
以上就是整个脚本的大致思路(不知道作者同不同意我这么说,只能说是作为新手的粗略理解)
他的url不全和我一样,我分析的url没有实践过,不过感觉应该也可以