前言:
最近在学习Python的爬虫,于是就想趁这个机会自己实战一下=w=
想到小爱同学可以通过教务系统自动获取课程表,我们学校还有其它一些公众号也可以获取,
于是我也尝试用Python把课程表爬下来。
(学校教务处还有官网都没有robots.txt文件,就当它默认让我爬了吧=w=
记录:
为了方便数据的处理还有锻炼一下之前学的知识,我是采用分析接口的方法进行爬取的,而不是从网页源代码里面获取。
一、登录部分
万事开头难嘛,我最开始也觉得这边有点东西。教务系统一般是需要登录之后才能使用的,于是我就从模拟登录开始做起。
首先用浏览器访问一下登录的地址,看一下是怎么请求的登录数据。
刚开始就遇到了问题,因为点击登录之后会跳转到其它页面,浏览器的开发者工具里面的network选项在网页刷新的时候默认是会清空的,因此除非手够快,根本就逮不到那一条想要的数据包。不过这个问题还是很好解决的,把上面的【保留日志】选项(或者叫Preserve Log)勾选即可,这样就能保存所有数据了。
就像上面那个图一样,我找到了CheckLogin的这一条数据,看描述是以POST的方式提交了一个表单。
里面有username字段,password字段,还有code和isautologin
因为我们教务系统是使用学号和密码进行登录的,分析可以得出,username那一段是经过处理的学号数据,password是明文的密码,这个很容易看出来,code应该是验证码功能,但是没有启用,然后isautologin应该是用于自动登录的。
学号那部分是怎么得到的呢?我又重新登录了几次,发现每次虽然输入了一样的学号,但是username却都不相同。
于是,我打开了网页的元素,发现了两个不同寻常的东西:
1.处理登录的js
2.一个写着publicKey的div标签
于是,带着这俩线索,我在网上搜索了一下JSEncrypt,得出了一个结论——登录的时候,username使用了RSA加密!
这下就很清晰明了了,既然知道了加密的方法,又知道了公钥,就可以用Python来模拟RSA加密的过程了!
于是我参考着教程写了一个用于RSA加密的Python函数:
导包导不进去除了文件夹改大写,还需要安装另一个库pycryptodome
(直接安装pycryptodome,就可以避免以上问题)
# RSA 公钥加密,用于登录教务系统处理用户名信息 def RSA_username(username): import base64 # 这里有可能出现导包导不进去的问题,把site-packages里面的crypto文件夹改为大写Crypto即可 from Crypto.PublicKey import RSA from Crypto.Cipher import PKCS1_v1_5 # 公钥在页面里面 key = '''-----BEGIN PUBLIC KEY----- MIGfMA0G***********************************************************自己去找公钥,这里不给你看***************/dMqixikUrd3H7llf79QIb3gRhIIZT8 TcpN6LUbX8noVcBKuwIDAQAB -----END PUBLIC KEY----- ''' rsakey = RSA.importKey(key) cipher = PKCS1_v1_5.new(rsakey) cipher_text = base64.b64encode(cipher.encrypt(username.encode(encoding='utf-8'))) value = cipher_text.decode('utf-8') return value
这样,我们就有了所有登录所需要的数据!
于是,我就尝试这用requests里面的session进行请求模拟登录,然而事情并不是那么一帆风顺……
直接请求肯定是不行的,因为缺少了一个叫ASP.NET_SessionId的cookie。于是,我先用session请求了一次登录页面,这样就能获取到这个cookie,然后再去请求checklogin。
这时我的headers里面只写了我浏览器相同的User-Agent,这次请求,他给我返回了一个页面不存在,然后是302跳转。。。
很显然,登录又失败了。。。
于是,我使用了电脑上的一个抓包工具Fiddler,分别抓取了我请求的那一条数据包和浏览器正常登录的数据包,并进行了请求头的比对
我发现我模拟请求的headers里面有很多缺失了,比如X-requested-with这个字段,可以用来验证ajax请求。
在充实了我的headers之后,我终于模拟请求成功了,获得了登录成功的提示!
{"type":1,"errorcode":0,"message":"登录成功。","resultdata":null}
就这样,重要的第一步——登录,完成了!!!
二、分析课程表数据接口并抓取
在登录之后,我们就可以进行课程表信息的获取了。
还是同样的办法,在network里面很容易找到请求课程表信息的接口(这接口提交的数据跟几个月前不一样了qwq怎么还会变的)
可以看到一共有三个字段,第一个字段里面是类似字典一样的数据类型,有学年和学期的数据,还有班级信息,下面那俩一个是根据什么排序(xsh?,课程号),另一个是正序或者倒序
最开始我模拟请求的时候真把第一个当字典直接请求了,然而那样是不行的,需要str(字典)转换成文本之后再请求才可以。
请求完之后,我们就可以对返回的数据进行分析了。返回的是Json格式的数据,我对它进行了分析处理。根据实际上课情况,我分析出了如下结果:
最后使用合适的方式对它进行解析、处理和储存、展示,就可以爬下来我们自己的课程表啦~
本文地址:https://blog.jixiaob.cn/?post=60
版权声明:若无注明,本文皆为“赵苦瓜のBlog~”原创,转载请保留文章出处。