新建爬虫类
初始化基础信息
1 | class PlannedCourseSpider: |
新建课程类
通过新建一个课程类,来方便管理获取到的课程信息
其中code被用作选课时的提交代码,构造数据包时要用到
1 | class Lesson: |
获取计划内课程
进入计划内课程页面
常规操作,逆向工程查看请求的URL和发送的数据
1 | def hello_zf(self): |
解析获取所有课程
分析网页源码,课程信息的存放大同小异,都是在一张table里面,第一项是抬头,获取抬头的兄弟节点。这里要注意这张网页的table最后有一个无效的tr标签,根据那个判断是否读完整张表。读取的信息可以存在之前用过的Lesson类里。这里用了正则表达式匹配课程代码,这个代码用于之后获取该课程的所有开课信息
1 | def get_all_lesson(selector): |
显示获取到的所有计划内课程,选择查看详细课程信息
把所有获取到的课程显示初恋,调用Lesson类的自带方法,选课也可以用到相同的方法,于是封装成一个类
1 | def show_and_select_lessons(lesson_list): |
获取课程的所有开课信息
根据选择的计划内课程,获取到那门课程的所有开课信息。
进入课程的信息页面
常规操作遇到坑,直接模拟获取信息的时候会在新窗口中打开。所以要按住Ctrl新建标签页面打开开课信息页面,然后在新打开的窗口中F12抓包。此时需要再发一次请求才能抓包,所以回到所有计划内课程页面,按住Ctrl再重新点击一次课程,之前打开抓包的那个页面就会刷新一次,抓到的数据也是需要的数据了
没啥新鲜的,Headers的referer改为发送请求的url,xkkh就是之前获取所有计划内课程信息里面的code,xh就是学号
1 | def hello_lesson(self, xkkh): |
这里用到了set_view_state修改Headers里面的__VIEWSTATE,分析源码发现,这个值总是出现在table的第三个隐藏input里面,后面选课的时候,要发送这个值
1 | def set_view_state(self, selector, from_name): |
获取该课程的所有信息
查看网页源码,跟之前完全类似的table结果,获取信息后储存到Lesson类中即可
1 | def get_all_information_of_lesson(selector, lesson): |
选课
手动模拟选课,查看POST的数据,比公选课简单的数据少一点
- ‘__EVENTTARGET’: ‘Button1’ 就是值为“选定”的那个button
- ‘__VIEWSTATE’: 前面获取到的那个东西,每发送一次请求,就会更新一次值
- ‘xkkh’: 这是课程里具体选择的那个老师的课的课程号,在前面获取所有信息的时候,已经储存在Lesson类的code信息里了
herders的referer还是要更新为当前发送请求的页面URL
1 | def select_lesson(self, lesson): |
用到的show_error是Lesson模块的方法,用Xpath定位页面的script,再用正则表达式匹配aleret信息,给出“现在不是选课时间”、“选课时间冲突”这样的提示
1 | def show_error(selector): |
完整代码
PlannedCourseSpider.py
1 | import Login as Lg |
Lesson.py
1 | import re |