文章目录

  • 1 总体介绍
  • 2 获取token的思路
  • 3 通过token访问成绩页面
  • 4 解析成绩页面返回的json
  • 5 导出数据到Excel


1 总体介绍

近日学校上线了家长督学系统。通过该系统,输入学生的证件号,即可查询学生的成绩。密码为证件号的后六位,刚好我有同学们的证件号。准备通过Python读取Excel中保存的证件号,然后模拟登陆,获得成绩信息,然后将所有同学的成绩输出到Excel,以便进行下一步的分析。

2 获取token的思路

通过抓包工具,可以看出在点击登录后,出现了“login”开头的一个请求,并在response中发现了“登陆成功”的字样。

python爬取强智教务系统成绩 爬虫教务系统_request


在这个json数据的后面,还找到了一个“token”,我猜测这个token就是用户的标识,标志着登陆成功,可能在后面涉及到用户信息查询的时候会用到这个token。

python爬取强智教务系统成绩 爬虫教务系统_request_02

然后查看请求的信息,使用post方式请求,url就是一个固定的前缀拼接上用户的账号和密码,而我刚好有这些信息。

python爬取强智教务系统成绩 爬虫教务系统_爬虫_03


然后进入查询成绩的页面进行查询,发现果然,token出现在了请求的头文件里,于是爬虫的思路就有了。第一步就是通过登录,获得到用户的token。

python爬取强智教务系统成绩 爬虫教务系统_爬虫_04


那就开始写代码啦,首先通过excel函数,将所需的账户名和密码从excel文件中提取出来。

密码为ID的后几位,截取字符串获得密码的操作在main函数中完成了,此处不予展示。

def excel(i):
    global user
    global pwd
    workBook = xlrd.open_workbook('data/all.xls')
    sheet1_content1 = workBook.sheet_by_index(0);
    id=sheet1_content1.cell(i, 0).value
    print(id)
    return id

然后通过拼接字符串的形式,将上一步中获取的账号和密码在Request URL中拼接出来,伪造一个浏览器的请求头,开始进行爬虫。然后将爬虫获取到的对象转换为json格式,发现该数据类型为字典,通过字典的基本语法,提取出了token的值。

def sprider1():
    head1 = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3861.400 QQBrowser/10.7.4313.400'
    }
    url='http://jwxtapp.nmu.edu.cn:8080/bfmzdxhd/patriarch/login?userNo='+user+'&pwd='+pwd
    r1=requests.get(url,headers=head1)
    r1.encoding='utf-8'
    json_token=r1.json()
    token=json_token['data']['token']
    # print(token)
    return token

3 通过token访问成绩页面

经过观察发现,成绩信息是向这个链接发送请求,然后返回的json数据中得到的。同时需要注意在请求头中添加上一步获得的token。

python爬取强智教务系统成绩 爬虫教务系统_request_05


代码实现如下,通过爬虫获得了返回的对象,成绩中有一些无用的字段,在此不做解析,只把它直接返回即可。

def sprider2(token):
    head2 = {
    'Referer': 'http://jwxtapp.nmu.edu.cn:8080/jzdxsjd/',
    'token': token,
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3861.400 QQBrowser/10.7.4313.400'
    }

    r2 = requests.get('http://jwxtapp.nmu.edu.cn:8080/bfmzdxhd/student/termGPA?semester=&type=', headers=head2)
    r2.encoding='utf-8'
    temp=r2.json()
    grade=temp["data"][0]
    return grade

4 解析成绩页面返回的json

该函数主要用于解析字段,需要用到的字段有:课程名,学分,成绩。所以建立几个空列表,用于存储。然后遍历整个grade列表,提取有用的子弹,并append入total列表,最后将列表total与字符串studentName在字典dic中对应起来,实现了一个学生全部成绩的存储。

def extract(grade):
    global dic
    i=0
    courseName=[]
    credit = []
    score = []
    total=[]
    studentName=grade["name"]
    x=len(grade['achievement'])
    while i<x:
        courseName.append(grade['achievement'][i]['courseName'])
        credit.append(grade['achievement'][i]['credit'])
        score.append(grade['achievement'][i]['fraction'])

        total.append(grade['achievement'][i]['courseName'])
        total.append(grade['achievement'][i]['credit'])
        total.append(grade['achievement'][i]['fraction'])
        i=i+1
    dic[studentName]=total

5 导出数据到Excel

使用函数分别遍历字典dic的key和value,并调用函数将遍历出来的信息写入excel中,因为value的值仍然是一个列表,所以需要用到循环再次进行遍历。
最后就实现了Excel中一个学生的姓名,后面一行对应着其所有的成绩的展示效果。

key=[]
values=[]
table={"1":"里面是不能公开的成绩的json数据"}
for i in dic.keys():
 key.append(i)
for j in dic.values():
 values.append(j)
print(key)
print(values)

list1=key
output = open('names.xls','w',encoding='gbk')
output.write('name\tgender\tstatus\tage\n')
for i in range(len(list1)):
    output.write(str(list1[i]))  #write函数不能写int类型的参数,所以使用str()转化
    output.write('\t')  #相当于Tab一下,换一个单元格
    output.write('\n')    #写完一行立马换行
output.close()