小小白祈祷中...

前言

又到了一年两度的四六级成绩查询的时候啦,不知道小伙伴们过了没有呢?

今天我们来介绍如何使用python来批量查询四六级成绩。听起来好像很高大上,但实现起来非常容易哦…

之前的爬虫博文中我也说过,爬虫最重要的一步不是如何编写程序,而是分析网页的结构。

四六级成绩查询可以使用如下网址:

http://cet.neea.edu.cn/html1/folder/22023/595-1.htm

分析网页

浏览器打开,随便进入一个入口,该网页中,按F12,我们来分析一下这个查询页面:

img

输入相关信息后,点击查询,可以看到对应的成绩,我们在控制台中,找找有什么好的接口可以直接查询到成绩,不一会儿,我们找到了下面这个文件:

img

这个文件的请求地址是:

http://cachecloud.neea.cn/api/latest/results/cet?e=CET_202112_DANGCI&km=2&xm=罗颖&no=4311******&v=

这个url地址有几个参数,我们关心的是xm(姓名)和no(身份证号),我们来看看这个请求的响应长什么样子:

img

显然,该请求返回的是一json串,我们来观察这个json串:

​ {

​ "xx":"******大学", (考生所在大学)

​ "tlmk":0,

​ "km":2,

​ "ky_sco":"",

​ "zkzh":"43003******", (准考证号)

​ "sfz":"43110******", (身份证号)

​ "score":"401", (六级成绩)

​ "sco_lc":"94", (听力部分成绩)

​ "ky_zkz":"–",

​ "xm":"***", (姓名)

​ "sco_rd":"175", (阅读部分成绩)

​ "sco_wt":"132", (写作部分成绩)

​ "id":"212243003004401",

​ "cjd":0,

​ "code":200 (状态码)

}

这里… "zkzh" 表示 "准考证号","sfz" 表示 "身份证",多少有点大病哈哈。。。

此外,如果查询不到(即没有参加六级考试或输入的信息有误),响应会是什么样的呢?

img

很显然,我们可以使用 "code" 这个键来判断某个学生是否参加了当次的六级考试(当然,前提是你的学生信息表中的信息没有错误…)。

爬取成绩

有了以上分析,我们就可以开始我们批量爬取六级成绩了。

首先,我们需要批量的考生信息数据,载体有很多,比如最常见的,excel表:

img

在数据导入的过程中需要一点 pandas 的知识,不会的小伙伴们可以去学一学哦。

在使用 pandas 处理得到的 DataFrame 中,我们添加几个字段用于存储爬取到的信息:

img

值得注意的是,如果直接调用之前分析的那个接口,会显示错误码403,这说明对方的服务器把我们已经将我们视为爬虫。一般的方法是,在请求的过程中,我们添加请求头,模拟我们使用浏览器进行查询。

请求头怎么弄呢?控制台上有现成的:

img

请求头中的所有属性中,最重要的是 Cookie属性(有兴趣的小伙伴们可以去查一查),简单来说,Cookie就是由服务器发给客户端(此处为浏览器)的特殊信息,这些信息存放在客户端(浏览器),然后客户端(浏览器)每次向服务器发送请求的时候都会带上这些特殊的信息,向浏览器表明自己的身份。

通俗来说,正因有了Cookie,对方的服务器才不会认为当前的请求是一个爬虫发出的,也就不会响应错误码403了,这样我们便可以拿到我们想要的数据。其余的属性,大家可选择性复制粘贴:

1
2
3
4
5
6
7
8
9
10
11
12
headers = {
'Accept': '*/*',
'Accept-Encoding': 'gzip, deflate',
'Accept-Language': 'zh-CN,zh;q=0.9',
'Connection': 'keep-alive',
'Host': 'cachecloud.neea.cn',
'Origin': 'http://cet.neea.cn',
'Referer': 'http://cet.neea.cn/',
'Cookie': 'Hm_lvt_dc1d69ab90346d8ee02f18510292577=1629958972,1629961007,1629989056,1629992054; community=Home; language=1; http_waf_cookie=f27d75db-23f7-4aa938445a95fb8092bcad0ba73630744bd3',
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/98.0.4758.102 Safari/537.36 '
}

接着,就是一些简单的爬取代码了。我们使用 requests 库来完成爬取工作。完整代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
from time import sleep
import requests
import pandas as pd

"""
:author: 易果啥笔
:date: 2022-01-24
:apiNote: 批量查询四六级成绩

"""

# 学生信息表data.xls,与源文件放在同一目录下
data = pd.read_excel('data.xls')

# 添加几个字段,用于存储爬取到的信息,
# 注意从7(索引从0开始)开始,因为我的表中前面已经有7个字段,这里需要根据自己的信息表调整
data.insert(7, '准考证号', '')
data.insert(8, '六级成绩', '')
data.insert(9, '听力部分', '')
data.insert(10, '阅读部分', '')
data.insert(11, '写作部分', '')

# 添加请求头
headers = {
'Accept': '*/*',
'Accept-Encoding': 'gzip, deflate',
'Accept-Language': 'zh-CN,zh;q=0.9',
'Connection': 'keep-alive',
'Host': 'cachecloud.neea.cn',
'Origin': 'http://cet.neea.cn',
'Referer': 'http://cet.neea.cn/',
'Cookie': 'Hm_lvt_dc1d69ab90346d48ee2f18510292577=1629958972,1629961007,1629989056,1629992054; community=Home; language=1; http_waf_cookie=f27d75db-23f7-4aa938445a95fb8092bcad0ba73630744bd3',
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/98.0.4758.102 Safari/537.36 '
}

# 由于是批量,用一个列表存储所有考生的参数
params_list = []
for i in range(len(data)):
params_list.append({
'e': 'CET_202112_DANGCI',
'km': 2,
'xm': data.iloc[i, 2],
'no': data.iloc[i, 6]
})

# 四六级成绩查询网址
url = "http://cachecloud.neea.cn/api/latest/results/cet"

# 遍历每一个考生的数据
for i in range(len(data)):
# requests.get(url,params,**args) **args可传入请求头headers
response = requests.get(url, params_list[i], headers=headers)
print("*******************************************************************")
print("开始爬取%s的六级成绩......" % params_list[i]['xm'])
# 由于response是json格式,可用response.json()接受
json_data = response.json()

# 判断学生是否参加了考试
if json_data['code'] == 200:
# 是,便开始存储成绩信息
data.iloc[i, 7] = json_data['zkzh'] # 准考证号
data.iloc[i, 8] = json_data['score'] # 六级分数
data.iloc[i, 9] = json_data['sco_lc'] # 听力部分
data.iloc[i, 10] = json_data['sco_rd'] # 阅读部分
data.iloc[i, 11] = json_data['sco_wt'] # 写作部分
info = '%d:%s查询成功,成绩为:%s' % ((i + 1), params_list[i]['xm'], json_data['score'])
print(info)
else:
# 否,输出相关信息
print('%d:%s未参加六级考试...' % ((i + 1), params_list[i]['xm']))
print("*******************************************************************")

# 休息0.3秒,防止爬取过快IP被封
sleep(0.3)

print("已全部查询完毕,正在导出到csv......")
# 导出至csv文件中
data.to_csv('grade.csv')
print("导出完毕.")

运行截图:

img程序跑完后,在当前目录下会生成指定的 grade.csv 文件,里面有所有学生的六级详细成绩。涉及隐私问题,这里就不截图了哈。

是不是挺简单的呢?