我就围着新海天转咯,书有得读,班也有得上,自己的朋友全都能联系,喜欢的事能一直坚持,就看着那些新海天写的逐字逐句露出的爱意,你能揣测出几百遍她爱我,你问我怎么办啊,好幸福,什么怎么办,要不然我抱紧新海天吧​

项目地址

开源代码

新海天作业通知机:https://github.com/10086mea/nimisora-homowork-notify

基本所有代码都是gpt写的,我本身并不怎么会代码(是真的)

订阅页面

https://love.nimisora.icu/homework-notify

油猴脚本自动填写验证码

BJTU智慧平台验证码自动填写

适配了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分钟查看本地文件检测一次要不要发邮件,减少对这个草台班子平台的负担(

人数再多点直接改改循环间隔就能变成一小时请求一波了(