This commit is contained in:
2025-07-09 00:17:36 +08:00
parent eebe92bab0
commit d56d2a3267
2 changed files with 87 additions and 80 deletions

42
main.py
View File

@ -1,11 +1,5 @@
from utils import LessonsException, ReloginException
from utils import sc_send,URP,logger
import re
from collections import deque
from os import environ
from pathlib import Path
from time import sleep, time
@ -13,14 +7,18 @@ from typing import Callable, List, Optional
import pandas as pd
from utils import URP, LessonsException, ReloginException, logger, sc_send
try:
from rich.markdown import Markdown
from rich import print
from rich.markdown import Markdown
RICH = True
except ImportError:
print("Some function in console may disabled due to no rich.")
RICH = False
class Lessons(URP):
def __init__(self):
super().__init__()
@ -32,7 +30,6 @@ class Lessons(URP):
self.interval_1 = int(environ.get("INTERVAL_1", 2)) # 请求间隔默认为2秒
self.interval_2 = int(environ.get("INTERVAL_2", 10)) # 请求间隔默认为10秒
def get_base_info(self):
res = self.session.get(f"{self.base}/student/courseSelect/gotoSelect/index")
res.raise_for_status()
@ -50,12 +47,12 @@ class Lessons(URP):
html = res.text
# 使用正则表达式替代 BeautifulSoup 来查找选中的学期选项
# 由于 HTML 结构特殊selected 在单独行上,需要向前查找对应的 option
lines = html.split('\n')
lines = html.split("\n")
for i, line in enumerate(lines):
if 'selected' in line.strip():
if "selected" in line.strip():
# 向前查找包含 option value 的行
for j in range(i - 1, max(0, i - 10), -1):
if 'option value=' in lines[j]:
if "option value=" in lines[j]:
value_match = re.search(r'value="([^"]*)"', lines[j])
if value_match:
self.term = str(value_match.group(1))
@ -227,7 +224,6 @@ class Lessons(URP):
logger.warning(f"选课 {cl[2]} 结果查询超时,可能未成功选课")
return False
def auto_spider(self):
"""自动选课主程序"""
try:
@ -299,7 +295,9 @@ class Lessons(URP):
raise e
except Exception as e:
errs.appendleft(time())
logger.error(f"选课 {cl[2]}_{cl[1]} 时发生错误: {e}")
logger.error(
f"选课 {cl[2]}_{cl[1]} 时发生错误: {e}"
)
finally:
sleep(self.interval_1) # 避免请求过快导致服务器拒绝
elif left == -1:
@ -343,6 +341,7 @@ class Lessons(URP):
sc_send("选课异常", desp=f"选课过程中发生意外错误: {e}")
raise e
class Grade(URP):
def __init__(self):
super().__init__()
@ -361,7 +360,9 @@ class Grade(URP):
res = self._retry_request(lambda: self.session.get(url))
res.raise_for_status()
html = res.text
match = re.search(f"/student/integratedQuery/scoreQuery/.+/thisTermScores/data",html)
match = re.search(
f"/student/integratedQuery/scoreQuery/.+/thisTermScores/data", html
)
if match:
url = self.base + match.group(0)
else:
@ -384,7 +385,6 @@ class Grade(URP):
def auto_check(self):
self.login()
# self.session.cookies.update({"student.urpSoft.cn":"aaapnXQb62LApgwx7lkFz","UqZBpD3n3iXPAw1X9DmYiUaISMkd8YhMUen0":"v1IraGSUs3hnH"})
grades = set()
self.query()
@ -424,7 +424,8 @@ class Grade(URP):
else:
print(t)
grades = new
if err > 0: err-=1
if err > 0:
err -= 1
except ReloginException as e:
logger.info("Relogin")
sc_send("成绩监控", "重新登录")
@ -443,9 +444,8 @@ class Grade(URP):
sc_send("成绩监控", "所有成绩均已公布")
if __name__ == "__main__":
# les = Lessons()
# les.auto_spider()
gra = Grade()
gra.auto_check()
les = Lessons()
les.auto_spider()
# gra = Grade()
# gra.auto_check()

View File

@ -1,29 +1,37 @@
from serverchan_sdk import sc_send as _sc_send
from datetime import datetime
import logging
from pathlib import Path
from os import environ
from dotenv import load_dotenv
import requests
import base64
import hashlib
import json
import logging
import re
from typing import NoReturn,Optional,Iterable
from datetime import datetime
from os import environ
from pathlib import Path
from typing import Iterable, NoReturn, Optional
import requests
from dotenv import load_dotenv
from serverchan_sdk import sc_send as _sc_send
class LessonsException(Exception):
"""自定义异常类"""
pass
class ReloginException(LessonsException):
"""用于处理需要重新登录的异常"""
pass
# 配置日志
logging.basicConfig(
level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s"
)
logger = logging.getLogger(__name__)
def sc_send(title: str, desp: str):
if not environ.get("SC_KEY"):
logger.error("SC_KEY 未设置,无法发送通知")
@ -43,6 +51,7 @@ def log_init():
file.setLevel(logging.INFO)
logger.addHandler(file) # 日志输出到文件
class URP:
def __init__(self, base=None):
self.session = requests.session()
@ -195,7 +204,6 @@ class URP:
if not flag:
raise LessonsException("登录失败无法获取token")
@staticmethod
def _judge_logout(response: requests.Response):
"""检查账号是否在其他地方被登录"""
@ -203,6 +211,5 @@ class URP:
raise ReloginException("有人登录了您的账号!")
load_dotenv(override=True)
log_init()