This commit is contained in:
ChuXun
2026-01-29 04:44:49 +08:00
parent d1dc08a16d
commit 2e0e4ea8c6
11 changed files with 0 additions and 490 deletions

View File

View File

@@ -1,202 +0,0 @@
# 问题修复说明
## 问题描述
服务器运行时出现以下错误:
```
[WARNING] 未能提取到成绩信息,返回原始文本
[INFO] 成绩无变化(共 0 门课程)
```
## 根本原因
成绩提取函数 `extract_grade_info` 在某些情况下无法正确解析HTML页面返回原始HTML文本导致 `parse_courses` 函数无法从原始HTML中提取课程信息。
可能的具体原因包括:
1. BeautifulSoup 库未安装
2. 登录会话失效,返回的是登录页面
3. 学校网页结构发生变化
4. 网络问题导致获取的HTML不完整
## 修复内容
### 1. 改进 `extract_grade_info` 函数 (monitor.py 第286-370行)
**新增功能:**
- ✅ 检测登录页面,返回特殊标记 `LOGIN_REQUIRED`
- ✅ 支持多种表格选择器(`gridtable`, `dataList`, 关键词搜索)
- ✅ 添加详细的调试日志(表头、行数等)
- ✅ 自动保存问题HTML到 `debug_page.html` 便于排查
- ✅ 提供成功提取的反馈信息
**改进代码片段:**
```python
# 检查是否是登录页面
if soup.find('input', {'name': 'username'}) or soup.find('input', {'name': 'password'}):
logger.error("检测到登录页面,可能需要重新登录")
return "LOGIN_REQUIRED"
# 尝试多种方式查找成绩表格
table = soup.find('table', {'class': 'gridtable'})
if not table:
table = soup.find('table', {'id': 'dataList'})
if not table:
# 尝试查找任何包含成绩相关标题的表格
for tbl in soup.find_all('table'):
headers = tbl.find_all('th')
if headers and any('课程名称' in th.get_text() or '成绩' in th.get_text() for th in headers):
table = tbl
logger.info("通过表头关键词找到成绩表格")
break
```
### 2. 改进 `parse_courses` 函数 (monitor.py 第347-378行)
**新增功能:**
- ✅ 检测 `LOGIN_REQUIRED` 标记
- ✅ 检测未解析的原始HTML
- ✅ 添加详细的解析日志
- ✅ 统计解析的课程数量
**改进代码片段:**
```python
# 检查是否需要重新登录
if grade_text == "LOGIN_REQUIRED":
logger.warning("检测到登录失效,需要重新登录")
return []
# 检查是否是原始HTML未成功解析的标记
if '<html' in grade_text.lower() or '<body' in grade_text.lower():
logger.warning("检测到未解析的HTML内容成绩提取可能失败")
logger.debug(f"文本前100字符: {grade_text[:100]}")
return []
```
### 3. 添加调试模式 (monitor.py 第743-797行)
**新增命令行参数:**
```bash
python3 monitor.py --debug # 启用详细日志
```
**功能:**
- 显示详细的调试信息
- 帮助快速定位问题
- 不影响正常运行模式
### 4. 创建诊断工具
**新增文件:**
1. **diagnose.sh** - 自动诊断脚本
- 检查依赖库安装
- 运行测试并分析结果
- 提供修复建议
2. **故障排查指南.md** - 详细的排查文档
- 常见问题及解决方案
- 调试流程说明
- 联系支持信息
3. **更新 常见问题解决.md** - 添加新问题说明
4. **更新 readme.md** - 添加快速诊断指引
## 使用方法
### 方式1自动诊断推荐
```bash
cd ~/grade_monitor
chmod +x diagnose.sh
./diagnose.sh
```
### 方式2手动调试
```bash
# 1. 检查依赖
pip3 install -r requirements.txt
# 2. 运行调试模式
python3 monitor.py --test --debug
# 3. 查看输出
cat .last_grade_content.txt
cat debug_page.html | head -50
# 4. 如果正常,重启服务
systemctl restart grade-monitor
```
### 方式3启用服务调试模式
编辑服务配置:
```bash
sudo nano /etc/systemd/system/grade-monitor.service
```
修改启动命令:
```ini
ExecStart=/usr/bin/python3 /home/yourusername/grade_monitor/monitor.py --debug
```
重新加载:
```bash
sudo systemctl daemon-reload
sudo systemctl restart grade-monitor
```
## 预期效果
### 正常运行时的日志
```
[DEBUG] 找到总平均绩点: 总平均绩点3.85
[DEBUG] 找到成绩表格
[DEBUG] 表头: ['学年学期', '课程代码', '课程序号', '课程名称', ...]
[DEBUG] 找到 15 行成绩数据
[INFO] 成功提取成绩信息,共 17 行
[DEBUG] 开始解析成绩,共 17 行
[DEBUG] 解析到课程: 高等数学A(1)
[DEBUG] 解析到课程: 线性代数
...
[INFO] 共解析到 15 门课程
[INFO] 成绩无变化(共 15 门课程)
```
### 出错时的日志
```
[WARNING] 未找到成绩表格
[WARNING] 未能提取到成绩信息,页面可能结构异常
[INFO] 已保存HTML到 /home/user/grade_monitor/debug_page.html 供调试
[WARNING] 检测到未解析的HTML内容成绩提取可能失败
[DEBUG] 文本前100字符: <!DOCTYPE html><html><head>...
[INFO] 共解析到 0 门课程
```
## 优势
1. **更好的错误提示** - 明确告知问题原因
2. **自动保存调试信息** - debug_page.html 便于排查
3. **灵活的表格查找** - 支持多种网页结构
4. **详细的日志** - 方便追踪每一步
5. **完善的文档** - 提供多种解决方案
## 注意事项
1. **不要过度使用调试模式** - 生产环境可能不需要
2. **定期检查 debug_page.html** - 了解实际获取的内容
3. **及时更新表格选择器** - 如果学校网页结构变化
4. **保护敏感信息** - debug_page.html 可能包含个人信息
## 下一步
如果问题仍未解决:
1. 查看 `debug_page.html` 的实际内容
2. 检查HTML中的表格结构
3. 可能需要调整 `extract_grade_info` 中的选择器
4. 咨询开发者或提交 Issue
---
**版本:** 2026-01-21
**修复人员:** GitHub Copilot
**测试状态:** 待用户测试确认

View File

@@ -1,94 +0,0 @@
# 修复说明 - 2026年1月22日
## 修复的问题
### 1. 日志重复输出问题
**现象**:每条日志都会输出两次
**原因**`logging.basicConfig()` 配置会在模块每次被导入时重复添加处理器,导致日志重复输出。
**解决方案**
- 使用 `if not logger.handlers:` 检查,确保处理器只被添加一次
- 设置 `logger.propagate = False` 防止日志传播到根记录器
- 使用显式的logger配置替代 `basicConfig`
### 2. 连续异常时自动重新登录
**现象**:当连续多次出现解析失败、获取页面失败或网络错误时,程序不会尝试重新登录,导致持续失败。
**解决方案**
在以下场景达到3次连续失败时自动触发重新登录
1. **获取成绩页面失败**
- 连续3次失败 → 尝试重新登录
- 登录成功 → 重置错误计数,继续监控
- 登录失败 → 继续累积错误计数
2. **网络错误(页面过短)**
- 连续3次网络错误 → 尝试重新登录
- 登录成功 → 重置错误计数
- 登录失败 → 继续累积错误计数
3. **解析课程失败0门课程**
- 连续3次解析失败 → 尝试重新登录
- 登录成功 → 重置错误计数
- 登录失败 → 发送通知,可能需要人工介入
## 技术细节
### 日志配置改进
```python
# 旧代码
logging.basicConfig(...)
logger = logging.getLogger(__name__)
# 新代码
logger = logging.getLogger(__name__)
if not logger.handlers:
# 配置处理器
logger.propagate = False
```
### 重新登录逻辑
```python
if consecutive_errors >= 3:
logger.warning("⚠️ 尝试重新登录以解决问题...")
if self.login():
logger.info("✓ 重新登录成功,重置错误计数")
consecutive_errors = 0
continue
else:
logger.error("✗ 重新登录失败")
```
## 使用建议
1. **重启服务**:修改后需要重启服务使改动生效
```bash
sudo systemctl restart grade-monitor
```
2. **查看日志**:确认日志不再重复
```bash
sudo journalctl -u grade-monitor -f
# 或
tail -f monitor.log
```
3. **监控效果**
- 日志应该只输出一次
- 连续3次异常会自动尝试重新登录
- 重新登录成功后会显示 "✓ 重新登录成功"
## 预期效果
- ✅ 日志不再重复输出
- ✅ 连续3次异常自动重新登录
- ✅ 重新登录成功后重置错误计数
- ✅ 减少因登录会话过期导致的持续失败
- ✅ 更好的容错性和自愈能力
## 注意事项
- 重新登录会记录在日志中,便于追踪
- 如果重新登录失败,仍会继续累积错误计数
- 达到5次最大连续错误后会发送邮件通知

View File

@@ -1,194 +0,0 @@
# 间歇性解析失败说明
## 现象
日志显示偶尔出现解析失败,但下一次检查又恢复正常:
```
17:34:05 - ✅ 成功提取成绩信息,共 14 行,解析到 8 门课程
17:36:12 - ✅ 成功提取成绩信息,共 14 行,解析到 8 门课程
17:38:12 - ❌ 未找到成绩表格,解析到 0 门课程
17:40:12 - ✅ 成功提取成绩信息,共 14 行,解析到 8 门课程
```
## 原因分析
这种**偶发性失败**通常是由以下原因造成的:
### 1. 网络波动(最常见)
- 数据包传输不完整
- HTML内容被截断
- 连接临时中断
### 2. 服务器临时问题
- 学校服务器负载高
- 短暂的维护或重启
- 数据库查询超时
### 3. WebVPN不稳定
- WebVPN代理服务波动
- SSL握手失败
- 重定向异常
### 4. 时机问题
- 正好在服务器更新数据时访问
- 缓存失效瞬间
- 负载均衡切换
## 改进措施
最新版本已添加**智能容错机制**
### 1. 识别网络错误
```python
# 检查HTML内容长度
if len(html) < 100:
logger.warning(f"HTML内容过短({len(html)}字节),可能是网络问题")
return "NETWORK_ERROR"
```
### 2. 自动重试
当检测到临时性问题时:
- ⚠️ 记录警告但不立即报错
- ⏱️ 等待30秒后自动重试
- 📊 只有连续3次失败才报警
### 3. 智能判断
```python
# 如果解析到0门课程但之前有课程记录
if len(current_courses) == 0 and len(previous_courses) > 0:
logger.warning("可能是临时问题30秒后重试")
time.sleep(30)
continue # 重新检查
```
### 4. 保存诊断信息
- 自动保存 `debug_page.html`
- 记录HTML长度和摘要
- 便于事后分析
## 预期行为
### 场景1偶发性失败正常
```
[INFO] 成功提取成绩信息,共 14 行
[INFO] 共解析到 8 门课程
[INFO] 等待 120 秒...
[WARNING] 未找到成绩表格
[WARNING] ⚠️ 解析到0门课程但之前有8门课程可能是临时问题
[INFO] 等待 30 秒后重试...
[INFO] 成功提取成绩信息,共 14 行 ← 重试成功
[INFO] 共解析到 8 门课程
```
### 场景2持续失败异常
```
[WARNING] ⚠️ 解析到0门课程可能是临时问题
[WARNING] 连续异常: 1/5
[WARNING] ⚠️ 解析到0门课程可能是临时问题
[WARNING] 连续异常: 2/5
[WARNING] ⚠️ 解析到0门课程可能是临时问题
[WARNING] 连续异常: 3/5 ← 开始报警
[ERROR] 连续 3 次无法解析课程之前有8门课程
```
## 判断标准
### ✅ 无需担心的情况
- 失败率 < 20%每10次失败少于2次
- 失败后1-2次就恢复
- 日志显示"等待30秒后重试"
- 下次检查自动恢复正常
### ⚠️ 需要关注的情况
- 失败率 > 20%
- 连续3次以上失败
- 日志显示"连续异常"
- 出现错误通知邮件
### 🚨 需要处理的情况
- 连续5次以上失败
- 失败率 > 50%
- 伴随"会话过期"错误
- debug_page.html 显示登录页面
## 统计失败率
使用诊断工具检查:
```bash
cd ~/grade_monitor
./diagnose.sh
# 或手动统计
echo "成功次数: $(grep -c '共解析到 [1-9]' monitor.log)"
echo "失败次数: $(grep -c '共解析到 0 门课程' monitor.log)"
```
## 最佳实践
### 1. 不要过度担心
- 偶尔失败是**正常现象**
- 程序已自动处理
- 只要失败率低,无需干预
### 2. 定期检查日志
```bash
# 查看最近的失败记录
grep "未找到成绩表格\|共解析到 0 门课程" ~/grade_monitor/monitor.log | tail -10
# 查看是否自动恢复
tail -n 20 ~/grade_monitor/monitor.log
```
### 3. 调整检查间隔
如果失败频繁,可以增加间隔:
```ini
[monitor]
CHECK_INTERVAL = 180 # 从120改为180秒
```
### 4. 信任自动化
- 程序会自动重试
- 只有持续失败才报警
- 收到邮件通知时再处理
## 何时需要手动干预
只在以下情况需要重启服务:
1. **连续多次收到错误邮件**
2. **日志显示持续登录失败**
3. **debug_page.html 显示异常内容**
4. **失败率持续超过50%**
其他情况下,让程序自动处理即可。
## 对比:改进前 vs 改进后
### 改进前
```
17:38:12 - ❌ 未找到成绩表格,解析到 0 门课程
17:38:12 - 成绩无变化(共 0 门课程) ← 直接当作正常
17:38:12 - 等待 120 秒... ← 不重试
17:40:12 - 开始新一轮检查 ← 2分钟后才重试
```
### 改进后
```
17:38:12 - ❌ 未找到成绩表格
17:38:12 - ⚠️ 解析到0门课程但之前有8门课程
17:38:12 - 等待 30 秒后重试... ← 智能判断
17:38:42 - ✅ 成功提取成绩信息 ← 快速恢复
```
---
**总结:** 偶发性失败是网络应用的正常现象。新版本通过智能重试机制,将影响降到最低。只要失败率在合理范围(<20%),无需任何手动干预。
**更新日期:** 2026-01-21
**版本:** v2.1 - 智能容错版