python实现今日校园APP自动签到(二)
文章目录
python实现今日校园APP自动签到(二)序言一、签到过程与脚本设计思路签到过程设计思路流程图
二、抓包分析交互过程获取的签到表单submit提交签到表单
三、脚本代码的具体实现主程序dailyCP.pyWid更新程序update.py保活脚本keepAlive.py用户账号信息文件test.json表单任务ID文件Wid.json
四、云服务器部署创建存放目录shell脚本的部署主程序run.sh更新程序update.sh保活程序keepAlive.sh
crontab计划任务的部署
总结
序言
上一期《python实现今日校园APP自动签到》发布之后,博主收到了小伙伴的私信,希望博主能协助这位小伙伴完成他学校的今日校园APP签到,一番交流后发现,不同的学校,签到的形式、具体用到的参数,相差甚远,原来的代码不能完完全全的直接复用,但编写的思路却是一样的,所以,本章节将给大家介绍一下某双一流大学今日校园APP自动签到的python编程。关于Charles抓包软件的设置和手机端网络代理设置的问题,可以参考上一期博文或其它资料,本文将不再赘述。
本文所有图片和代码,均已脱敏处理。
一、签到过程与脚本设计思路
签到过程
经过交流后得知,该校的签到是,一天签到三次,分早中晚三个时段。
早上 7:00~8:30 中午 12:00~13:30 晚上 22:00~23:00
三次签到,必须在这三个对应的时间段内;除此之外,还有定位限制,必须在要学校范围内,超出范围的无法签到
设计思路
有了签到的过程,那么我们就可以着手开始设计。每天3次签到,那么签到的主程序每天要执行3次,而且要在对应的时间段内执行; 考虑到3次签到的表单ID都不一样,所以表单ID的更新脚本,也要随之执行3次;最后则是保活脚本,为了让cookie能一直有效,需要不停的去访问任意页面,实现cookie的保活,这个每隔20分钟执行一次就好。
流程图
二、抓包分析交互过程
获取的签到表单
首先,分别打开早中晚三次签到的页面,看看charles抓包到的内容(图片已脱敏处理)
早晨签到的包: 中午签到的包: 晚上签到的包:
再对比多个早中晚的三个抓包,其实很容易发现的是,客户端每次都会向服务器请求两个参数:signInstanceWid和signWid
其中,signInstanceWid是表单ID,从早到晚,每次都不一样,且无规律递增;
signWid则是对应早中晚三个任务的ID,这里称它为任务ID,每次都是固定这三个值:
早(466705)
中(466703)
晚(466708)
submit提交签到表单
submit提交签到的包:
从抓包中可以得知,传递的核心参数是signInstanceWid,也就是签到表的ID,其它的像longitude(经度)、latitude(维度)、position(定位地址)这些,说白了都是固定值,我人在校园内,那么这些值每次肯定都是一样的,可以直接写死。extraFieldItems是签到时额外弹出的框,要学生填写体温信息的,只要你体温正常不发烧,那么每次也都是这个数值(58679)。
三、脚本代码的具体实现
知悉了交互过程和传递的参数,那么就可以开始写脚本了
主程序dailyCP.py
'''
==========================
=====POWER BY python3=====
======Author Task138======
==========================
'''
import requests
, json
, warnings
, datetime
warnings
.filterwarnings
('ignore')
def getData(cookie
, signInstanceWid
):
now_hour
= datetime
.datetime
.now
().hour
sign_hour
= 0
if now_hour
< 9:
sign_hour
= 7
elif now_hour
< 14:
sign_hour
= 12
else:
sign_hour
= 23
print(now_hour
, sign_hour
)
if sign_hour
== 7:
signWid
= '466705'
elif sign_hour
== 12:
signWid
= '466703'
else:
signWid
= '466708'
print(signInstanceWid
, signWid
)
info
= {}
info
['signInstanceWid'] = signInstanceWid
headers
= {
'Host': '这里填写抓包得到的学校域名',
'Content-Type': 'application/json',
'Cookie': cookie
,
'Accept': '*/*',
'Accept-Language': 'zh-cn',
'Accept-Encoding': 'gzip, deflate, br',
'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 (4833404928)cpdaily/8.2.1 wisedu/8.2.1',
'Connection': 'keep-alive',
'Origin': '这里填写抓包得到的学校域名'
}
url
= '这里填写获取表单详情信息的URL'
body
= {
'signInstanceWid': signInstanceWid
,
'signWid': signWid
}
data
= json
.dumps
(body
)
req
= requests
.post
(url
=url
, data
=data
, verify
=False, headers
=headers
)
thread
= 200
for i
in range(thread
+ 1):
body
= {
'signInstanceWid': str(int(signInstanceWid
) + i
),
'signWid': signWid
}
data
= json
.dumps
(body
)
req
= requests
.post
(url
=url
, data
=data
, verify
=False, headers
=headers
)
response
= json
.loads
(req
.text
)
now
= datetime
.datetime
.today
()
current_date
= now
.strftime
('%Y-%m-%d')
try:
senderUserName
= response
['datas']['senderUserName']
sign_date
= response
['datas']['rateSignDate']
rateTaskBeginTime
= response
['datas']['rateTaskBeginTime']
print(rateTaskBeginTime
, body
['signInstanceWid'])
except:
print(body
)
continue
if ('这里填写辅导员的名字' in senderUserName
) and (current_date
in sign_date
):
if signWid
== '466705':
if rateTaskBeginTime
!= '07:00':
continue
if signWid
== '466703':
if rateTaskBeginTime
!= '12:00':
continue
if signWid
== '466708':
if rateTaskBeginTime
!= '22:00':
continue
new_signInstanceWid
= response
['datas']['signInstanceWid']
try:
wid
= response
['datas']['extraField'][0]['extraFieldItems'][0]['wid']
except:
wid
= 58679
info
['signInstanceWid'] = new_signInstanceWid
info
['wid'] = wid
if new_signInstanceWid
!= signInstanceWid
:
with open('Wid.json', 'w') as fp3
:
new_data
= '{"signInstanceWid":"%s"}' % (new_signInstanceWid
)
fp3
.write
(new_data
)
fp3
.close
()
print('更新成功,当前数值:')
print('signInstanceWid [ %s ]' % new_signInstanceWid
)
break
else:
print(senderUserName
)
return info
def submitForm(cookie
, info
, username
):
headers
= {
'Host': '这里填写抓包得到的学校域名',
'Content-Type': 'application/json',
'Cpdaily-Extension': '7Q881vmOiX7oHMgy2uiNNl8ZFV6TrEm+YxKkdJOzmMMGgT2eTPPHxBxY02LK 4Qq42SCAuunYl3r52lBcvtJAKSbT6h1n94BA3spnuAfnh7YCJbOJpAxjn9mx X8a8G9i9OYPNioL6UB76/x7ZeuZly9Ai1L6sAFWwtkczAcTdTSKdx+aqI5XO xPbqJrAztcBx+CtvFlsMsGcI2uKHLD3I2sgoFB4XoYhFv/4SjuWX+N/W24Oy oF8txhaTS1PJhmetIYLybnMWyAoiH6lmwknAMjSJdtqLe51u',
'Cookie': cookie
,
'Accept': '*/*',
'Accept-Language': 'zh-cn',
'Accept-Encoding': 'gzip, deflate, br',
'User-Agent': '%E4%BB%8A%E6%97%A5%E6%A0%A1%E5%9B%AD/1 CFNetwork/1128.0.1 Darwin/19.6.0',
'Connection': 'keep-alive'
}
url
= '这里填写post提交表单的URL'
body
= {
"signInstanceWid": info
['signInstanceWid'],
"longitude": 这里填写抓包抓取到的经度
,
"latitude": 这里填写抓包抓取到的维度
,
"isMalposition": 0,
"abnormalReason": "",
"signPhotoUrl": "",
"position": "这里填写定位的地址信息",
"isNeedExtra": 1,
"extraFieldItems": [{
"extraFieldItemValue": "小于37.3℃",
"extraFieldItemWid": info
['wid']
}]
}
data
= json
.dumps
(body
)
req
= requests
.post
(url
=url
, headers
=headers
, data
=data
, verify
=False)
response
= req
.text
print(response
)
if "SUCCESS" in response
:
print('[ %s ]签到成功' % username
)
return True
elif "该收集已填写无需再次填写" in response
:
print('[ %s ]签到成功' % username
)
return True
elif "该收集已结束!" in response
:
print('[ %s ]签到成功' % username
)
return True
elif "该签到已截止!" in response
:
print('[ %s ]签到成功' % username
)
return True
else:
print('[ %s ]签到失败' % username
)
return False
if __name__
== '__main__':
success
= 0
failed
= 0
failed_data
= []
with open('test.json', 'r') as fp2
:
accounts
= json
.load
(fp2
)
fp2
.close
()
for k
, v
in accounts
.items
():
with open('Wid.json', 'r') as fp
:
data
= json
.load
(fp
)
fp
.close
()
signInstanceWid
= data
['signInstanceWid']
address
= v
['address']
cookie
= v
['cookie']
info
= getData
(cookie
, signInstanceWid
)
submitForm
(cookie
, info
, k
)
Wid更新程序update.py
'''
=================================
=================================
=========Author:Task138==========
========Power By Python3=========
=================================
=================================
'''
import requests
, json
, warnings
, time
, platform
, datetime
, threading
, random
with open('Wid.json', 'r') as fp
:
data
= json
.load
(fp
)
fp
.close
()
signInstanceWid
= data
['signInstanceWid']
warnings
.filterwarnings
('ignore')
def getData(cookie
, signInstanceWid
):
now_hour
= datetime
.datetime
.now
().hour
sign_hour
= 0
if now_hour
< 9:
sign_hour
= 7
elif now_hour
< 14:
sign_hour
= 12
else:
sign_hour
= 23
print(now_hour
, sign_hour
)
if sign_hour
== 7:
signWid
= '466705'
elif sign_hour
== 12:
signWid
= '466703'
else:
signWid
= '466708'
print(signInstanceWid
, signWid
)
info
= {}
info
['signInstanceWid'] = signInstanceWid
headers
= {
'Host': '这里填写抓包得到的学校域名',
'Content-Type': 'application/json',
'Cookie': cookie
,
'Accept': '*/*',
'Accept-Language': 'zh-cn',
'Accept-Encoding': 'gzip, deflate, br',
'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 (4833404928)cpdaily/8.2.1 wisedu/8.2.1',
'Connection': 'keep-alive',
'Origin': '这里填写抓包得到的学校域名'
}
url
= '这里填写获取表单详情信息的URL'
body
= {
'signInstanceWid': str(int(signInstanceWid
)+1),
'signWid': signWid
}
data
= json
.dumps
(body
)
req
= requests
.post
(url
=url
, data
=data
, verify
=False, headers
=headers
)
thread
= 200
for i
in range(thread
+ 1):
body
= {
'signInstanceWid': str(int(signInstanceWid
) + i
),
'signWid': signWid
}
data
= json
.dumps
(body
)
req
= requests
.post
(url
=url
, data
=data
, verify
=False, headers
=headers
)
response
= json
.loads
(req
.text
)
now
= datetime
.datetime
.today
()
current_date
= now
.strftime
('%Y-%m-%d')
try:
senderUserName
= response
['datas']['senderUserName']
sign_date
= response
['datas']['rateSignDate']
rateTaskBeginTime
= response
['datas']['rateTaskBeginTime']
print(rateTaskBeginTime
, body
['signInstanceWid'])
except:
print(body
)
continue
if ('这里填写辅导员的名字' in senderUserName
) and (current_date
in sign_date
):
if signWid
== '466705':
if rateTaskBeginTime
!= '07:00':
continue
if signWid
== '466703':
if rateTaskBeginTime
!= '12:00':
continue
if signWid
== '466708':
if rateTaskBeginTime
!= '22:00':
continue
new_signInstanceWid
= response
['datas']['signInstanceWid']
try:
wid
= response
['datas']['extraField'][0]['extraFieldItems'][0]['wid']
except:
wid
= 58679
info
['signInstanceWid'] = new_signInstanceWid
info
['wid'] = wid
if new_signInstanceWid
!= signInstanceWid
:
with open('Wid.json', 'w') as fp3
:
new_data
= '{"signInstanceWid":"%s"}' % (new_signInstanceWid
)
fp3
.write
(new_data
)
fp3
.close
()
print('更新成功,当前数值:')
print('signInstanceWid [ %s ]' % new_signInstanceWid
)
break
else:
print(senderUserName
)
return info
with open('test.json', 'r') as fp2
:
accounts
= json
.load
(fp2
)
fp2
.close
()
for k
, v
in accounts
.items
():
with open('Wid.json', 'r') as fp
:
data
= json
.load
(fp
)
fp
.close
()
cookie
= v
['cookie']
signInstanceWid
= data
['signInstanceWid']
getData
(cookie
, signInstanceWid
)
保活脚本keepAlive.py
'''
=================================
=================================
=========Author:Task138==========
========Power By Python3=========
=================================
=================================
'''
import json
, requests
, warnings
warnings
.filterwarnings
('ignore')
def keepAlive(cookie
, signInstanceWid
):
headers
= {
'Host': '这里填写抓包得到的学校域名',
'Content-Type': 'application/json',
'Cookie': cookie
,
'Accept': '*/*',
'Accept-Language': 'zh-cn',
'Accept-Encoding': 'gzip, deflate, br',
'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 (4833404928)cpdaily/8.2.1 wisedu/8.2.1',
'Connection': 'keep-alive',
'Origin': '这里填写抓包得到的学校域名'
}
url
= '这里填写获取表单详情信息的URL'
body
= {
'signInstanceWid': signInstanceWid
,
"signWid":"466705"
}
data
= json
.dumps
(body
)
req
= requests
.post
(url
=url
, data
=data
, verify
=False, headers
=headers
)
response
= json
.loads
(req
.text
)
status
= response
['message']
print(status
)
return status
if __name__
== '__main__':
with open('test.json', 'r') as fp2
:
accounts
= json
.load
(fp2
)
fp2
.close
()
for k
, v
in accounts
.items
():
with open('Wid.json', 'r') as fp
:
data
= json
.load
(fp
)
fp
.close
()
signInstanceWid
= data
['signInstanceWid']
cookie
= v
['cookie']
status
= keepAlive
(cookie
, signInstanceWid
)
if status
== 'SUCCESS':
print('[ %s ] 保活成功' % k
)
else:
print('[ %s ] 保活失败' % k
)
用户账号信息文件test.json
{
"用户姓名(必须用Unicode编码)": {
"cookie": "抓包抓到的cookie",
"address": "定位地址(必须用Unicode编码)"
}
}
表单任务ID文件Wid.json
{"signInstanceWid":"35176"}
四、云服务器部署
创建存放目录
mkdir
-p
/data/dailyCP
随后进入dailyCP,把上述py脚本和json配置文件,存放进里面
shell脚本的部署
主程序run.sh
current_date=$
(date
"+%Y_%m_%d")
log_name=
"${current_date}.log"
if [ ! -d
"./log" ]; then
mkdir
./log
fi
if [ ! -f
"./log/$log_name" ]; then
touch
./log
/$log_name
fi
current_time=$
(date
"+%Y_%m_%d_%H_%M_%S")
echo $current_time >>
./log
/$log_name
python3
/data/dailyCP
/dailyCP
.py >>
./log
/$log_name
echo -e >>
./log
/$log_name
echo "done"
更新程序update.sh
current_date=$
(date
"+%Y_%m_%d")
log_name=
"${current_date}.log"
if [ ! -d
"./update_log" ]; then
mkdir update_log
fi
if [ ! -f
"./update_log/$log_name" ]; then
touch
./update_log
/$log_name
fi
current_time=$
(date
"+%Y_%m_%d_%H_%M_%S")
echo $current_time >>
./update_log
/$log_name
python3
/data/dailyCP
/updateWid
.py >>
./update_log
/$log_name
echo -e >>
./update_log
/$log_name
echo "done"
保活程序keepAlive.sh
python3
/data/dailyCP
/keepAlive
.py
crontab计划任务的部署
*/20
* * * * cd
/data/dailyCP && sh keepAlive
.sh
30 7
* * * cd
/data/dailyCP && sh run
.sh
30 12
* * * cd
/data/dailyCP && sh run
.sh
30 22
* * * cd
/data/dailyCP && sh run
.sh
10 7
* * * cd
/data/dailyCP && sh update
.sh
10 12
* * * cd
/data/dailyCP && sh update
.sh
10 22
* * * cd
/data/dailyCP && sh update
.sh
总结
这次的脚本的编写难度,相比上一期明显容易了很多,很多参数都是表面上的动态变量,实际上都可视为静态量。
最后必须申明,本文仅用于python的技术学习与交流,切勿用于其它非法用途,如果你真有发烧等疑似症状,一定要及时上报自己的主管部门或者学校单位,《中华人民共和国传染病防治法》第八章法律责任第六十五条~第七十七条已明确规定,未依照本法的规定履行职责,或者隐瞒、谎报、缓报传染病疫情,亦或者其他违法行为的都有相应的处罚规定;构成犯罪的,依法追究刑事责任。