[Python]校园网网页认证:打造无人值守的智能重连守护进程
1. 为什么需要校园网守护进程校园网网页认证是很多大学生和科研工作者每天都要面对的日常操作。每次电脑重启或者网络波动后都需要手动打开浏览器输入账号密码登录这个过程既繁琐又容易被打断。特别是在实验室远程操作电脑时一旦断网就意味着要亲自跑一趟机房重新登录非常影响工作效率。我实验室的服务器就经常遇到这个问题。有次出差在外突然发现无法远程连接实验室电脑后来才知道是宿舍区临时停电导致网络断开。等我赶回去处理时已经耽误了重要实验数据的采集。这种经历让我下定决心要开发一个真正可靠的自动登录解决方案。传统的自动登录脚本有个明显缺陷它们往往只在开机时运行一次。但校园网环境复杂断网可能发生在任何时候 - 路由器重启、WiFi信号弱、认证会话过期等等。我们需要的是一个能7×24小时在后台默默工作的守护者时刻监控网络状态发现问题立即自动修复。2. 环境准备与基础配置2.1 Python环境搭建推荐使用Miniconda来管理Python环境它能很好地解决不同项目间的依赖冲突问题。我习惯为每个项目创建独立环境这里我们新建一个名为campus_net的环境conda create -n campus_net python3.9 conda activate campus_net接着安装必要的包pip install requests psutil pyinstaller其中requests用于网络请求psutil用来监控系统状态pyinstaller则是打包工具。建议使用VS Code或PyCharm作为开发环境它们的代码提示和调试功能能大幅提升开发效率。2.2 分析校园网认证流程不同学校的认证页面可能差异很大但基本原理相似。以我们学校为例打开认证页面http://10.10.10.9输入账号密码点击登录浏览器会发起一个GET请求形如http://10.10.10.9:801/eportal/?cPortalaloginuser_account学号user_password密码wlan_user_ip当前IP关键是要用浏览器开发者工具F12抓取这个真实的登录请求。在Chrome的Network标签页点击登录后找到第一个请求右键选择Copy→Copy as cURL就能看到完整的请求URL。3. 核心代码实现3.1 基础登录功能我们先实现最基本的登录功能。创建一个login.py文件import requests import socket from datetime import datetime def get_local_ip(): 获取本机IP地址 s socket.socket(socket.AF_INET, socket.SOCK_DGRAM) try: s.connect((10.255.255.255, 1)) ip s.getsockname()[0] except Exception: ip 127.0.0.1 finally: s.close() return ip def campus_login(username, password): 校园网登录函数 base_url http://10.10.10.9:801/eportal/ params { c: Portal, a: login, login_method: 1, user_account: username, user_password: password, wlan_user_ip: get_local_ip(), wlan_user_mac: 000000000000 } try: resp requests.get(base_url, paramsparams, timeout10) if resp.status_code 200: print(f[{datetime.now()}] 登录成功) return True except Exception as e: print(f[{datetime.now()}] 登录异常: {str(e)}) return False这个版本已经可以实现基本登录但还不够智能。我们需要让它能自动检测网络状态并在断网时自动重连。3.2 网络状态检测单纯检查登录状态是不够的因为校园网可能会把我们踢下线。更可靠的方法是定期检测真实网络连通性import time import psutil def check_internet_connection(test_urlhttp://connect.rom.miui.com/generate_204): 检测真实网络连接状态 try: resp requests.get(test_url, timeout5) return resp.status_code 204 except: return False def network_monitor(username, password, check_interval300): 网络状态监控主循环 while True: if not check_internet_connection(): print(f[{datetime.now()}] 检测到网络断开尝试重新登录...) campus_login(username, password) # 检查校园网特定登录状态 try: resp requests.get(http://10.10.10.9, timeout5) if 注销页 not in resp.text: campus_login(username, password) except: pass time.sleep(check_interval)这里使用了小米的204检测接口因为它响应快且稳定。check_interval建议设置为5分钟300秒既不会给服务器造成压力又能及时发现问题。4. 进阶功能优化4.1 异常处理与重试机制网络环境复杂我们需要更健壮的异常处理def safe_login(username, password, max_retries3): 带重试机制的登录函数 for attempt in range(max_retries): if campus_login(username, password): return True time.sleep(5 * (attempt 1)) # 指数退避 return False def smart_network_monitor(username, password): 智能网络监控 consecutive_failures 0 while True: try: if not check_internet_connection(): print(f[{datetime.now()}] 网络异常第{consecutive_failures1}次尝试恢复...) if safe_login(username, password): consecutive_failures 0 else: consecutive_failures 1 # 如果连续失败超过阈值延长检查间隔 wait_time 300 if consecutive_failures 5 else 1800 time.sleep(wait_time) except Exception as e: print(f[{datetime.now()}] 监控异常: {str(e)}) time.sleep(60)这个版本增加了失败计数和动态等待机制。连续失败时会自动延长检查间隔避免在完全无网络环境下频繁重试。4.2 资源占用优化作为守护进程资源占用要尽可能低def daemon_main(): 守护进程主函数 # 降低进程优先级 import os if hasattr(os, nice): os.nice(10) # Linux/Mac elif hasattr(os, priority): os.setpriority(os.PRIO_PROCESS, 0, 10) # Windows # 读取配置文件 with open(config.json) as f: config json.load(f) # 启动监控 smart_network_monitor(config[username], config[password])我们还应该添加日志功能方便排查问题import logging from logging.handlers import RotatingFileHandler def setup_logging(): 配置日志系统 logger logging.getLogger(campus_net) logger.setLevel(logging.INFO) # 文件日志最大1MB保留3个备份 file_handler RotatingFileHandler( campus_net.log, maxBytes1024*1024, backupCount3) file_handler.setFormatter(logging.Formatter( %(asctime)s - %(levelname)s - %(message)s)) logger.addHandler(file_handler) return logger5. 部署与使用指南5.1 打包为可执行文件使用PyInstaller打包时建议添加这些参数pyinstaller -F -w --add-data config.json;. login.py-F参数生成单个可执行文件-w隐藏控制台窗口Windows适用--add-data将配置文件一起打包。5.2 开机自启动配置Windows系统将生成的login.exe创建快捷方式WinR输入shell:startup打开启动文件夹将快捷方式拖入即可Linux系统systemd服务sudo tee /etc/systemd/system/campusnet.service EOF [Unit] DescriptionCampus Network Daemon Afternetwork.target [Service] ExecStart/path/to/login Restartalways Useryourusername [Install] WantedBymulti-user.target EOF sudo systemctl enable campusnet sudo systemctl start campusnet5.3 配置文件说明建议使用JSON格式的配置文件config.json{ username: 你的学号, password: 你的密码, check_interval: 300, test_url: http://connect.rom.miui.com/generate_204 }这样既安全又方便修改不需要重新打包程序。记得把配置文件放在与可执行文件相同的目录下。6. 实际使用中的经验分享在实验室部署这个守护进程半年多来遇到过几个典型问题值得分享首先是IP地址变化问题。有些校园网会频繁更换分配的IP导致之前的登录会话失效。解决方法是在get_local_ip()函数中增加IP变化检测发现变化立即重新登录。其次是认证服务器不稳定。遇到服务器响应慢时简单的timeout可能不够。我后来增加了服务器状态检测如果连续多次请求超时就自动延长检查间隔避免雪崩效应。最棘手的是多设备登录限制。有些校园网会限制同时在线设备数。针对这种情况我修改了代码在每次登录前先尝试注销其他设备def force_logout(username): 强制注销其他设备 logout_url http://10.10.10.9:801/eportal/?cPortalalogout requests.get(logout_url) time.sleep(1) # 等待注销完成最后是关于安全性。虽然GET请求方便但URL中的密码是明文传输的。如果学校支持建议改用POST方式并在代码中使用加密存储密码。