2023-05-20:使用python库来实现定时任务,不再依赖系统的定时任务,部署起来容易100倍
说在前面
大部分校园网都需要认证才能够上网,而且就算你保持在线隔一段时间也会将你强行踢下线,导致游戏中断,自己挂在校园网的web程序宕机等头疼的问题。
本文主要是使用python与主机的计划任务来实现校园网的自动认证,需要注意的是,我们学校的校园网认证系统与认证方式可能与你们学校的不一样,所以主要是分享我的实现思路,以供大家参考参考。
准备工作:
- 一台电脑
- 一台用于挂载自动认证脚本的服务器(也可以是你的电脑,或者不那么硬的路由器之类的)
了解校园网认证的过程
这是最繁琐的一步,在网上见过的这么多认证的教程,感觉我们学校是最复杂的
其实总结来说这一步就是反复的在浏览器f12里观察你在认证的时候都经过了哪些程序,我们学校的认证流程大概是这样的
我们需要传入以下参数进行认证,其中后三项传空值,因为是本地认证后面脚本就懒得加密密码了,把passwordEncrypt传false,password直接明文就可以了,可能不安全,但校园网无所谓。
看起来感觉实现很容易对不对?python随便几行request就能实现了的。但有以下几个问题:
- 重复的认证是无效的,不会重新计算在线时间(到点还是踢你)
- 高频的认证可能导致莫名奇妙的bug,比如明明已经认证成功了而认证服务器那边确觉得你没有认证,导致认证界面直接卡死(因为123.123.123.123在你已经接入互联网的情况下是无法访问的)
- 多次认证还可能导致出现验证码,目前脚本还无法处理验证码
于是我们在程序中需要判断是否已经认证了,在已经认证的情况下运行程序需要先登出来重置在线时间从而推迟强制下线的时间(于是,我们又需要找到两个请求:一个是判断认证情况的,一个是退出登录的)
经过疯狂的F12和api调试之后,找到了172.208.2.102/eportal/InterFace.do?method=logout
与172.208.2.102/eportal/InterFace.do?method=getUserInfo
两个api来进行登出和判断操作
python实现
认证流程用python的requests库很容易就能实现,定时任务用schedule来创建也很容易。
import re
import time
import urllib.parse
from urllib.parse import urlparse
import requests
import schedule
apiUrl = "http://172.208.2.102/eportal/InterFace.do"
authUrl = apiUrl + "?method=login"
logoutUrl = apiUrl + "?method=logout"
getQueryUrl = "http://123.123.123.123/"
getUserInfoUrl = apiUrl + "?method=getOnlineUserInfo"
webService = "中国电信"
# 判断是否已经认证了
def is_authed():
try:
resp = requests.get(getUserInfoUrl, timeout=3)
if resp.status_code != 200:
# 网络问题直接退出
print("判断认证状态失败")
return False
else:
json_data = resp.json()
result = json_data["result"]
return result != "fail"
except requests.RequestException:
print("判断认证状态失败: 请求失败")
return False
# 获取query认证信息
def get_query_str():
try:
resp = requests.get(getQueryUrl, timeout=8)
if resp.status_code != 200:
print("获取query信息失败")
return False
pattern = "href='(.*)'"
match = re.search(pattern, resp.text)
if match:
url = urlparse(match.group(1))
return url.query
else:
return None
except requests.RequestException:
print("获取query信息失败: 请求失败")
return False
# 认证
def do_auth():
query_str = get_query_str()
if not query_str:
return False
# 表单数据
data = {
"userId": "871390441",
"password": "yourpassword",
"service": urllib.parse.quote(webService),
"queryString": query_str,
"passwordEncrypt": "false",
"operatorPwd": None,
"operatorUserId": None,
"validcode": None
}
try:
resp = requests.post(authUrl, data)
if resp.status_code == 200 and resp.json()["result"] == "success":
print("认证成功")
return True
else:
print("认证失败")
return False
except requests.RequestException:
print("认证失败: 请求失败")
return False
# 退出登录
def do_logout():
resp = requests.get(logoutUrl)
if resp.status_code == 200:
if resp.json()["result"] == "success":
print("退出登录成功")
return True
else:
print("退出登录失败: " + resp.json()["message"])
return False
else:
print("退出登录失败: 网络错误")
return False
# 一次认证流程
def auth_job():
print("\n====校园网自动认证开始====")
if is_authed():
if do_logout():
do_auth()
else:
do_auth()
print("====校园网自动认证结束====\n")
if __name__ == '__main__':
auth_job()
# 定时任务
schedule.every().day.at("12:00").do(auth_job)
schedule.every().day.at("00:00").do(auth_job)
while True:
schedule.run_pending()
time.sleep(1)
代码部分有了思路之后其实就很简单了,接下来就是最重要的部署环节了。
部署到服务器
我这里以部署到我的破烂x86linux服务器上为例(windows就更简单了,直接运行python程序即可),采取docker部署的方式
首先写Dockerfile, 这里我就不解释了,不懂的话找一找资料吧
FROM python:3.11-slim-bullseye
WORKDIR /app
ADD . /app
RUN pip3 config set global.index-url http://mirrors.aliyun.com/pypi/simple && \
pip3 config set install.trusted-host mirrors.aliyun.com && \
pip install --upgrade pip &&\
pip3 install requests &&\
pip3 install schedule
CMD python3 -u main.py
然后在当前文件夹输入命令来建立镜像和运行容器,很简单对不对
docker build -t autoauth:v1 .
docker run --restart always --name myautoauth autoauth:v1
写在最后
以上操作在我这是完美运行的,需要一些折腾,但你能看完我这篇博客说明你肯定也是个喜欢折腾的人吧。上面的一些命名方法路径之类的不一定是绝对的。