XJTU全校课表的爬虫demo

'# XJTU全校课表的爬虫demo

一、背景与问题

西安交通大学(XJTU)的全校课表系统是典型的Web应用,其核心功能包括学生查询个人课表、教师查询教学安排、管理员维护课程信息等。作为一个典型的B/S架构系统,其数据存储通常采用MySQL/PostgreSQL等关系型数据库,前端通过Spring Boot、Django等框架渲染页面。

在实际开发中,我们常遇到以下问题:

  1. 教务系统数据接口不开放,无法直接调用API
  2. 课表数据需要用户登录后才能查看
  3. 页面内容存在JavaScript动态渲染
  4. 存在反爬虫机制(如验证码、请求频率限制)

本篇文章将深入分析XJTU课表系统的爬虫实现方案,重点探讨如何在不违反服务条款的前提下,通过合法途径获取数据。

二、基本原理

XJTU课表系统的核心数据存储结构通常包含以下表:

  • courses(课程信息):包含课程编号、名称、学分、上课时间等
  • teachers(教师信息):包含教师工号、姓名、所属学院
  • schedule(课表安排):关联课程、教室、时间、教师等
  • users(用户信息):包含学号、姓名、所属院系

数据访问流程如下:

  1. 用户通过浏览器访问 https://xjtu.edu.cn/course 路径
  2. 前端发送AJAX请求到 /api/schedule 接口
  3. 后端从数据库查询数据并返回JSON格式
  4. 前端通过JavaScript渲染课表表格

三、环境准备

# 安装Python依赖
pip install requests beautifulsoup4 lxml selenium

四、核心实现

1. 网站分析与请求模拟

import requests
from bs4 import BeautifulSoup

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4443.114 Safari/537.36'
}

# 获取登录页面
login_url = 'https://xjtu.edu.cn/login'
response = requests.get(login_url, headers=headers)
soup = BeautifulSoup(response.text, 'lxml')

# 分析登录参数(假设存在hidden字段)
csrf_token = soup.find('input', {'name': 'csrf_token'})['value']

关键代码解释:

  • 使用User-Agent模拟浏览器访问
  • 通过BeautifulSoup解析HTML,提取隐藏字段
  • 注意处理可能存在的CSRF令牌验证

2. 登录与会话管理

login_data = {
    'username': 'your_username',
    'password': 'your_password',
    'csrf_token': csrf_token
}

# 创建会话对象
session = requests.Session()
session.post(login_url, headers=headers, data=login_data)

关键代码解释:

  • 使用requests.Session()保持会话状态
  • 需要处理可能的验证码验证(如使用第三方OCR服务)

3. 课表数据爬取

schedule_url = 'https://xjtu.edu.cn/api/schedule'
response = session.get(schedule_url, headers=headers)
data = response.json()

# 解析课表数据
for course in data['courses']:
    print(f"课程名称: {course['name']}, 时间: {course['time']}, 教室: {course['room']}")

关键代码解释:

  • 直接调用API接口获取JSON数据
  • 需要处理可能的分页参数(如page=1、page=2)

五、完整案例

1. 完整爬虫脚本(带异常处理)

import requests
from bs4 import BeautifulSoup
import json
import time
import logging

# 配置日志
logging.basicConfig(level=logging.INFO)

def get_csrf_token():
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4443.114 Safari/537.36'
    }
    login_url = 'https://xjtu.edu.cn/login'
    response = requests.get(login_url, headers=headers)
    soup = BeautifulSoup(response.text, 'lxml')
    return soup.find('input', {'name': 'csrf_token'})['value']

def login(username, password):
    csrf_token = get_csrf_token()
    login_data = {
        'username': username,
        'password': password,
        'csrf_token': csrf_token
    }
    session = requests.Session()
    session.post('https://xjtu.edu.cn/login', data=login_data)
    return session

def fetch_schedule(session):
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4443.114 Safari/537.36'
    }
    schedule_url = 'https://xjtu.edu.cn/api/schedule'
    try:
        response = session.get(schedule_url, headers=headers)
        response.raise_for_status()
        return response.json()
    except Exception as e:
        logging.error(f"请求失败: {str(e)}")
        return None

if __name__ == '__main__':
    session = login('your_username', 'your_password')
    if session:
        schedule_data = fetch_schedule(session)
        if schedule_data:
            print(json.dumps(schedule_data, indent=2))

关键代码解释:

  • 使用try-except块处理网络异常
  • 模拟登录流程后获取会话对象
  • 处理可能的API限流(添加time.sleep(1))

六、源码解析

1. 请求头构造

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4443.114 Safari/537.36'
}

关键点:

  • 必须使用符合标准的User-Agent
  • 部分网站会检测UA字段,使用Chrome/Firefox等浏览器UA更易通过验证

2. 响应处理

response = session.get(schedule_url, headers=headers)
response.raise_for_status()

关键点:

  • raise_for_status()会检查HTTP状态码,4xx/5xx会抛出异常
  • 需要处理可能的重定向(如allow_redirects=True)

七、进阶使用

1. 爬虫调度器

from datetime import datetime

def schedule_crawler(username, password, interval=3600):
    while True:
        try:
            session = login(username, password)
            if session:
                schedule_data = fetch_schedule(session)
                if schedule_data:
                    print(f"{datetime.now()}: 爬虫任务完成")
                else:
                    print("未获取到课表数据")
            time.sleep(interval)
        except Exception as e:
            print(f"发生异常: {str(e)}")
            time.sleep(60)

关键点:

  • 使用定时任务定期获取数据
  • 需要处理可能的登录失效问题(如会话过期)

2. 数据持久化

import sqlite3

def save_to_sqlite(data):
    conn = sqlite3.connect('schedule.db')
    c = conn.cursor()
    c.execute('CREATE TABLE IF NOT EXISTS schedule (id INTEGER PRIMARY KEY, course TEXT, time TEXT, room TEXT)')
    for item in data['courses']:
        c.execute("INSERT INTO schedule (course, time, room) VALUES (?, ?, ?)", 
                  (item['name'], item['time'], item['room']))
    conn.commit()
    conn.close()

关键点:

  • 使用SQLite存储数据(可扩展为MySQL/PostgreSQL)
  • 注意处理SQL注入问题(使用参数化查询)

八、性能与工程实践

1. 性能优化方案

优化措施说明
并发请求使用concurrent.futures.ThreadPoolExecutor
缓存机制使用requests_cache库缓存响应
资源复用使用requests.Session()保持连接
限流控制设置合理的请求间隔(如1秒)

2. 异常处理策略

def safe_request(url, headers, max_retries=3):
    for i in range(max_retries):
        try:
            response = requests.get(url, headers=headers)
            response.raise_for_status()
            return response.json()
        except requests.exceptions.RequestException as e:
            logging.warning(f"第{i+1}次请求失败: {str(e)}")
            time.sleep(2 ** i)
    return None

关键点:

  • 处理网络波动和服务器故障
  • 使用指数退避算法重试

3. 安全风险分析

风险类型防范措施
验证码识别使用第三方OCR服务(如百度AI)
IP封禁使用代理IP池
请求频率限制设置合理的请求间隔
数据泄露对敏感数据进行加密处理

九、常见问题与踩坑

1. 常见错误及解决方案

错误类型错误示例解决方案
403 Forbiddenrequests.get()返回403检查User-Agent,添加Referer头
500 Internal Server Error服务器端错误检查API接口是否变更
JSON解析错误json.loads()报错检查响应内容是否为JSON格式
验证码识别失败验证码识别错误使用第三方识别服务

2. 反爬虫机制应对

# 添加Referer头
headers = {
    'User-Agent': 'Mozilla/5.0',
    'Referer': 'https://xjtu.edu.cn/course'
}

关键点:

  • 部分网站要求Referer头
  • 需要分析目标网站的请求头特征

十、最佳实践

  1. 数据存储:建议使用关系型数据库存储课表数据,便于后续查询和分析
  2. 异常处理:每个请求都应该包含重试机制和异常捕获
  3. 日志记录:详细记录请求和响应内容,便于排查问题
  4. 配置管理:将敏感信息(如用户名密码)存储在配置文件中,避免硬编码
  5. 合规性:遵守《中华人民共和国计算机信息系统安全保护条例》,不用于非法用途

十一、总结

XJTU课表系统的爬虫实现涉及多个技术点:

  • 网络请求与会话管理
  • HTML解析与JSON数据处理
  • 异常处理与性能优化
  • 安全风险防控

本篇文章通过完整案例展示了如何在不违反服务条款的前提下,通过合法途径获取课表数据。需要注意的是,爬虫技术应遵守相关法律法规,不得用于非法用途。在实际开发中,建议优先考虑官方API接口,只有在必要时才使用爬虫技术。

对于需要处理大量数据或复杂业务场景的项目,可以考虑以下扩展方向:

  1. 使用Scrapy框架构建分布式爬虫
  2. 集成数据库事务处理保证数据一致性
  3. 添加数据校验逻辑确保数据质量
  4. 实现可视化界面供用户查询课表数据

通过本篇文章的深入探讨,我们不仅掌握了XJTU课表系统的爬虫实现方法,更重要的是理解了爬虫技术的使用边界和工程实践要点。在实际开发中,需要根据具体需求选择最合适的解决方案。

none
最后修改于:2026年10月03日 13:13

评论已关闭

推荐阅读

AIGC实战——Transformer模型
2024年12月01日
Socket TCP 和 UDP 编程基础(Python)
2024年11月30日
python , tcp , udp
如何使用 ChatGPT 进行学术润色?你需要这些指令
2024年12月01日
AI
最新 Python 调用 OpenAi 详细教程实现问答、图像合成、图像理解、语音合成、语音识别(详细教程)
2024年11月24日
ChatGPT 和 DALL·E 2 配合生成故事绘本
2024年12月01日
omegaconf,一个超强的 Python 库!
2024年11月24日
【视觉AIGC识别】误差特征、人脸伪造检测、其他类型假图检测
2024年12月01日
[超级详细]如何在深度学习训练模型过程中使用 GPU 加速
2024年11月29日
Python 物理引擎pymunk最完整教程
2024年11月27日
MediaPipe 人体姿态与手指关键点检测教程
2024年11月27日
深入了解 Taipy:Python 打造 Web 应用的全面教程
2024年11月26日
基于Transformer的时间序列预测模型
2024年11月25日
Python在金融大数据分析中的AI应用(股价分析、量化交易)实战
2024年11月25日
AIGC Gradio系列学习教程之Components
2024年12月01日
Python3 `asyncio` — 异步 I/O,事件循环和并发工具
2024年11月30日
llama-factory SFT系列教程:大模型在自定义数据集 LoRA 训练与部署
2024年12月01日
Python 多线程和多进程用法
2024年11月24日
Python socket详解,全网最全教程
2024年11月27日
python之plot()和subplot()画图
2024年11月26日
理解 DALL·E 2、Stable Diffusion 和 Midjourney 工作原理
2024年12月01日