我就围着新海天转咯,书有得读,班也有得上,自己的朋友全都能联系,喜欢的事能一直坚持,就看着那些新海天写的逐字逐句露出的爱意,你能揣测出几百遍她爱我,你问我怎么办啊,好幸福,什么怎么办,要不然我抱紧新海天吧
项目地址
开源代码
新海天作业通知机:https://github.com/10086mea/nimisora-homowork-notify
基本所有代码都是gpt写的,我本身并不怎么会代码(是真的)
订阅页面
https://love.nimisora.icu/homework-notify
油猴脚本自动填写验证码
适配了http://123.121.147.7:88/ve/和http://study.bjtu.top:88/ve两种访问方式
效果演示:

致谢
再次感谢草台班子队伍的新成员——智慧课程平台,下面列举一下它草台班子的点
- 使用IP访问,没有域名没有HTTPS http://123.121.147.7:88/ve/ ,因此直接用
study.bjtu.top
做了个解析把它吞并了。可以使用 http://study.bjtu.top:88/ve 进行访问 - 验证码明文返回进行比对,形同虚设
- 重置密码接口只检测cookie有效性不检测账户,可以随便重置别人密码(在某个搞笑事件发生后该重置接口已关闭)

实现思路&踩坑
项目后端使用python实现,前端是用PHP把用户user_data.json跟html接起来的,新加了个页面让GPT美化了一下,并非wordpress的扩展。
踩坑
- 部分老师布置作业时设置了24:00这个抽象时间,需要特殊处理
- 部分老师布置了重名作业,需要使用课程ID作为索引
- 课程平台不定时抽风导致请求失败,需要给所有请求相关代码添加重试机制
- 有人密码不是默认密码,需要添加异常处理自动跳过
Cookie部分
def initialize_session(base_url):
"""初始化会话并获取初始的cookie和JSESSIONID。"""
session = requests.Session()
captcha_url_png = f"{base_url}/GetImg"
# 获取初始cookie
response = session.get(base_url)
session.get(captcha_url_png)
if response.status_code == 200:
print("已获取初始cookie。")
jsessionid = session.cookies.get('JSESSIONID')
if jsessionid:
print("已获取JSESSIONID:", jsessionid)
return session, jsessionid
else:
raise Exception("在cookie中未找到JSESSIONID。")
else:
raise Exception("获取初始cookie失败。")
获取到JSESSIONID这个会话cookie就行了
验证码部分
def get_captcha(session, base_url):
"""获取验证码。"""
captcha_url_png = f"{base_url}/GetImg"
session.get(captcha_url_png)
captcha_url = f"{base_url}/confirmImg"
response = session.get(captcha_url)
if response.status_code == 200 and response.text:
captcha = response.text
print("已获取验证码:", captcha)
return captcha
else:
raise Exception("获取验证码失败。")
由于页面上的验证码是以src形式引入的
<img title="点击更换" onclick="javascript:refresh(this);" src="GetImg" id="GetImg" class="checkImg">
所以在请求http://123.121.147.7:88/ve/confirmImg获取明文返回的验证码内容前,需要请求一下http://123.121.147.7:88/ve/GetImg加载验证码,否则confirmImg内容为空
登录部分
def perform_login(session, base_url, student_id, jsessionid, captcha):
"""使用学号和验证码进行登录。"""
login_url = f"{base_url}/s.shtml"
password = f"Bjtu@{student_id}"
headers = {
"User-Agent": "Mozilla/5.0",
"Accept": "application/json, text/javascript, */*; q=0.01",
"cookies": jsessionid
}
data = {
"username": student_id,
"password": md5(password),
"passcode": captcha
}
response = session.post(login_url, data=data, headers=headers, allow_redirects=True)
print("已发送登录请求,状态码:", response.status_code)
if response.status_code == 200:
print("登录成功。")
else:
raise Exception("登录失败。")
账号是学号,密码是防止有人干坏事还是不说了,passcode就是获取到的验证码,注意post的时候密码要先计算成md5值再传
作业内容获取
使用浏览器登入课程平台,F12打开控制台看网络部分,这种传了一堆参数的双击打开就是一个json文件。

主要使用的json:
获取当前学期xqCode,用于获取课程列表 | http://123.121.147.7:88/ve/back/rp/common/teachCalendar.shtml?method=queryCurrentXq |
传入xqCode,获取课程列表,课程的id用于请求作业列表 | http://123.121.147.7:88/ve/back/coursePlatform/course.shtml?method=getCourseList&pagesize=100&page=1&xqCode={xqCode} |
获取作业列表,cld是课程id,subType:0对应作业,1对应课程报告,2对应实验 | http://123.121.147.7:88/ve/back/coursePlatform/homeWork.shtml?method=getHomeWorkList&cId={ID}&subType=0&page=1&pagesize=100 |
获取用户信息 | http://123.121.147.7:88/ve/back/coursePlatform/userInfo.shtml?method=getUserInfo |
邮件提醒部分
代码太多了不贴了,每个用户可以设定两个阈值,用来分割成阈值外、普通、紧急三个分类。把爬到的未提交的作业储存到每个用户对应的csv文件里,附带上紧急类型。每次检测要不要提醒的时候就比对一下这次跟上次的reminder列表内容有没有变化。
设定Ubuntu环境的系统任务
startup-script.sh
#!/bin/bash
# 设置conda的基础路径
CONDA_BASE=$(conda info --base)
# 检查是否已存在homework_notify的screen会话,如果存在则终止
if screen -list | grep -q "homework_notify"; then
echo "存在正在运行的'homework_notify' screen会话"
screen -S homework_notify -X quit
# 等待一小段时间确保screen会话已经完全关闭
sleep 1
fi
# 创建新的screen会话
echo "创建一个新的'homework_notify'screen会话"
screen -dmS homework_notify bash -c "source $CONDA_BASE/etc/profile.d/conda.sh && \
conda activate homework && \
cd /path/to/nimisora-homowork-notify && \
$CONDA_BASE/envs/homework/bin/python main.py; \
exec bash"
echo "作业提醒脚本已经在名为'homework_notify'的screen窗口启动,使用screen -r homework_notify进入它"
添加可执行权限
sudo mv startup-script.sh /path/to/nimisora-homowork-notify/
sudo chmod +x /path/to/nimisora-homowork-notify/startup-script.sh
Systemd服务文件 homework-notify.service
[Unit]
Description=Homework Notification Service
After=network.target
[Service]
Type=oneshot
User=YOUR_USERNAME
ExecStart=/bin/bash -c 'screen -list | grep -q "homework_notify" && screen -S homework_notify -X quit; sleep 1; screen -dmS homework_notify bash -c "cd /path/to/nimisora-homowork-notify && /root/miniconda3/envs/homework/bin/python main.py; exec bash"'
RemainAfterExit=yes
Restart=on-failure
RestartSec=5s
[Install]
WantedBy=multi-user.target
设置自启动
# 将YOUR_USERNAME替换为您的用户名
sudo sed -i "s/YOUR_USERNAME/$(whoami)/g" homework-notify.service
# 复制服务文件到systemd目录
sudo cp homework-notify.service /etc/systemd/system/
# 重新加载systemd配置
sudo systemctl daemon-reload
# 启用服务(设置开机自启)
sudo systemctl enable homework-notify.service
# 立即启动服务
sudo systemctl start homework-notify.service
# 检查服务状态
sudo systemctl status homework-notify.service
使用手册
screen -r homework_notify
sudo systemctl status homework-notify.service
sudo systemctl start homework-notify.service
sudo systemctl stop homework-notify.service
future
之后学一下php接入到https://bjtu.top论坛上,再做个网页用来提供订阅服务以及设定提醒阈值。
订阅页面:https://love.nimisora.icu/homework-notify/
用的人多了以后还可以再优化一下,目前是隔15分钟全部请求一次,订阅人数过多以至于现在请求一遍就要7min了
以后可以每小时更新一次作业list,每15分钟查看本地文件检测一次要不要发邮件,减少对这个草台班子平台的负担(
人数再多点直接改改循环间隔就能变成一小时请求一波了(