暨南大学教务处排课选课表爬取

暨南大学教务处排课选课表爬取

这段代码是寒假的时候写的,没想到现在还能运行,可以整理好教务处的排课选课列表然后做一些有趣的数据分析。

获取数据

自在是爬取,都分为两步:第一步获得数据,第二步进行数据处理。所以首先需要获取数据。因为需要登入教务处才能看到排课选课列表,所以如果想要直接请求数据的话,需要curl。但是对于这个问题,使用curl是多此一举的。我们首先进入排课选课表:

注意把每页行数改成总共的行数,不加任何筛选条件的话是3547行。
接下来打开检查,找到这个页面:

选择copy response,然后把copy的内容粘贴到文本文件中保存为csv文件即可。
下面这个是我保存的:
paikexuanke.csv

数据处理

到这里我们就算是请求到了我们需要的数据,如果你安装好了curl(Mac系统是自带的)。你也可以选择copy as cURL, 不过你会发现,那串命令长极了!所以还是用我上面介绍的方法吧!
然后就是我开头所说的那段代码,用那段代码处理一下这个csv文件就能获得一个整理好的数据集了。

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
clear all
cap mkdir "~/Desktop/课表"
cd "~/Desktop/课表"
utrans paikexuanke.csv
insheet using paikexuanke.csv, clear
tostring v8 v10 v11 v12 v14, replace
replace v1 = v1 + v2 + v3 + v4 + v5 + v6 + v7 + v8 + v9 + v10 + v11 + v12 + v13 + v14 + v15
drop v2-v15
keep if index(v1, "<td>") | index(v1, "</span>")
drop in 1/10
replace v1 = subinstr(v1, " ", "", .)
split v1, parse(</td><td>)
drop v1
compress
drop if v11 == "....." & v12 == ""
drop v18
gen 上课地点 = ""
gen 上课时间 = ""
gen 排课班号 = ""
gen 招生对象 = ""
gen 考试日期 = ""
gen 考试时间 = ""
gen 备注 = ""
gen 方式 = ""
forval i = 1/`=_N'{
if index(v11[`i'], "<td>") & index(v11[`i'+4], "<td>"){
replace 上课地点 = v11[`i'+1] if _n == `i'
replace 上课时间 = v11[`i'+2] if _n == `i'
replace 排课班号 = v12[`i'+3] if _n == `i'
replace 招生对象 = v13[`i'+3] if _n == `i'
replace 考试日期 = v14[`i'+3] if _n == `i'
replace 备注 = v15[`i'+3] if _n == `i'
replace 方式 = v16[`i'+3] if _n == `i'
}
if index(v11[`i'], "<td>") & index(v11[`i'+5], "<td>"){
replace 上课地点 = v11[`i'+1] if _n == `i'
replace 上课时间 = v11[`i'+2] if _n == `i'
replace 排课班号 = v12[`i'+3] if _n == `i'
replace 招生对象 = v13[`i'+3] if _n == `i'
replace 考试日期 = v14[`i'+3] if _n == `i'
replace 考试时间 = v11[`i'+4] if _n == `i'
replace 备注 = v12[`i'+4] if _n == `i'
replace 方式 = v13[`i'+4] if _n == `i'
}
}
drop if v17 == ""
replace v11 = subinstr(v11, "<td>", "", .)
replace 上课地点 = ustrregexs(1) if ustrregexm(上课地点, ">(.*)<")
replace 上课时间 = ustrregexs(1) if ustrregexm(上课时间, ">(.*)<")
foreach i of varlist _all{
replace `i' = "" if `i' == "&nbsp;"
format `i' %15s
replace `i' = subinstr(`i', "<td>", "", .)
replace `i' = subinstr(`i', "</td>", "", .)
replace `i' = subinstr(`i', "南校区教学楼", "", .)
replace `i' = subinstr(`i', "南校区", "", .)
}
destring v13 v14 v17, replace
rename v11 课程编号
rename v12 课程名称
rename v13 排课限制
rename v14 选课人数
rename v15 主讲教师
rename v16 专业名称
rename v17 学分
format 学分 %2.1f
gen date = date(考试日期, "YMD")
format date %dCY-N-D
drop 考试日期
rename date 考试日期
replace 方式 = subinstr(方式, ".....", "", .)
format 考试时间 %15s
destring, replace
save 排课选课表, replace


我把这个文件存储到了我的cuse数据库里面,命名为jdcourse2018b.dta
安装了cuse数据库之后就能直接运行下面的命令调用该数据集:

1
cuse jdcourse2018b.dta, c w

一些简单的分析

色块图

运行下面的代码即可得到一个矩阵A:

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
cuse jdcourse2018b, clear w
* 经过我研究发现,上课地点变量不带汉字的是在南校区开的课。下面是用正则表达式实现这一操作:
keep if !ustrregexm(上课地点, "[\u4e00-\u9fa5]+")
replace 上课时间 = ustrregexs(1) if ustrregexm(上课时间, "\)(.*)")
replace 上课时间 = subinstr(上课时间, "①", "", .)
replace 上课时间 = subinstr(上课时间, "②", "", .)
replace 上课时间 = subinstr(上课时间, "单周", "", .)
replace 上课时间 = subinstr(上课时间, "双周", "", .)
replace 上课时间 = subinstr(上课时间, "(1-16)", "", .)
order 上课时间
drop if 上课时间 == ""
drop if !index(上课时间, "周")
contract 上课时间 [fw = 选课人数]
gsort 上课时间
format 上课时间 %60s
drop if index(上课时间, "(")
save temp, replace

use temp, clear
matrix A = J(12, 5, .)
local j = 1
foreach i in "一" "二" "三" "四" "五"{
use temp, clear
keep if index(上课时间, "周`i'-1,")
sum _freq
matrix A[1, `j'] = r(sum)
use temp, clear
keep if index(上课时间, "周`i'-1,2")
sum _freq
matrix A[2, `j'] = r(sum)
use temp, clear
keep if index(上课时间, "周`i'-1,2,3") | index(上课时间, "周`i'-3")
sum _freq
matrix A[3, `j'] = r(sum)
use temp, clear
keep if index(上课时间, "周`i'-1,2,3,4") | index(上课时间, "周`i'-3,4")
sum _freq
matrix A[4, `j'] = r(sum)
use temp, clear
keep if index(上课时间, "周`i'-6")
sum _freq
matrix A[6, `j'] = r(sum)
use temp, clear
keep if index(上课时间, "周`i'-6,7") | index(上课时间, "周`i'-7")
sum _freq
matrix A[7, `j'] = r(sum)
use temp, clear
keep if index(上课时间, "周`i'-6,7,8") | index(上课时间, "周`i'-7,8")
sum _freq
matrix A[8, `j'] = r(sum)
use temp, clear
keep if index(上课时间, "周`i'-6,7,8,9") | index(上课时间, "周`i'-7,8,9") | index(上课时间, "周`i'-8,9") | index(上课时间, "周`i'-9")
sum _freq
matrix A[9, `j'] = r(sum)
use temp, clear
keep if index(上课时间, "周`i'-10")
sum _freq
matrix A[10, `j'] = r(sum)
use temp, clear
keep if index(上课时间, "周`i'-10,11") | index(上课时间, "周`i'-11")
sum _freq
matrix A[11, `j'] = r(sum)
use temp, clear
keep if index(上课时间, "周`i'-10,11,12") | index(上课时间, "周`i'-11,12") | index(上课时间, "周`i'-12")
sum _freq
matrix A[12, `j'] = r(sum)
local j = `j' + 1
}
mat list A

矩阵A为:

1
2
3
4
5
6
7
8
9
10
11
12
13
c1    c2    c3    c4    c5
r1 2533 2676 2057 1373 1492
r2 2533 2676 2057 1373 1492
r3 3999 4031 3368 2894 2542
r4 3919 4031 3368 2894 2542
r5 . . . . .
r6 4833 4751 4073 165 2525
r7 4858 4751 4172 165 2582
r8 3210 3434 2810 52 2225
r9 460 279 439 0 145
r10 3416 2799 2656 1983 516
r11 3543 2799 2656 1983 516
r12 2918 2327 2250 1458 305

其行分别表示周一到周五,列表示第一节到第十二节课。
使用这个矩阵就可以绘制一些炫酷的图,例如绘制一个色块图:

1
2
plotmatrix, m(A) c(green) ylabel(,angle(0)) leg(off) aspect(1)
gre jdcourse2018b

使用ECharts绘制三维柱形图

还可以用下面的代码绘制一副三维柱形图:

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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
clear
input 节 周 选课人数
0 0 .
1 0 .
2 0 .
3 0 .
4 0 .
5 0 .
6 0 .
7 0 .
8 0 .
9 0 .
10 0 .
0 1 .
1 1 .
2 1 .
3 1 .
4 1 .
5 1 .
6 1 .
7 1 .
8 1 .
9 1 .
10 1 .
0 2 .
1 2 .
2 2 .
3 2 .
4 2 .
5 2 .
6 2 .
7 2 .
8 2 .
9 2 .
10 2 .
0 3 .
1 3 .
2 3 .
3 3 .
4 3 .
5 3 .
6 3 .
7 3 .
8 3 .
9 3 .
10 3 .
0 4 .
1 4 .
2 4 .
3 4 .
4 4 .
5 4 .
6 4 .
7 4 .
8 4 .
9 4 .
10 4 .
end
local j = 1
forval n = 1/5{
foreach m in 1 2 3 4 6 7 8 9 10 11 12{
replace 选课人数 = A[`m', `n'] in `j'
local j = `j' + 1
}
}
save 每节课的选课人数, replace
clear
jscopy
fw, s h(选课人数的三维柱形图)
lib, b s(vintage)
fw `"var clss = ['第一节课', '第二节课', '第三节课', '第四节课', '第六节课', '第七节课', '第八节课', '第九节课','第十节课','第十一节课','第十二节课'];"'
fw `"var week = ['周一', '周二', '周三', '周四', '周五'];"'
fw `"var data = ["'
use 每节课的选课人数, clear
forval i = 1/`=_N'{
local var `"[`=节[`i']',`=周[`i']',`=选课人数[`i']'],"'
fw `"`var'"'
}
fw `"];"'
fw `"option = {"'
fw `" visualMap: {"'
fw `" max: 10000,"'
fw `" inRange: {"'
fw `" color: ['#313695', '#4575b4', '#74add1', '#abd9e9', '#e0f3f8', '#ffffbf', '#fee090', '#fdae61', '#f46d43', '#d73027', '#a50026']"'
fw `" }"'
fw `" },"'
fw `" xAxis3D: {"'
fw `" name: '',"'
fw `" type: 'category',"'
fw `" data: week"'
fw `" },"'
fw `" yAxis3D: {"'
fw `" name: '',"'
fw `" type: 'category',"'
fw `" data: clss"'
fw `" },"'
fw `" zAxis3D: {"'
fw `" name: '',"'
fw `" type: 'value'"'
fw `" },"'
fw `" grid3D: {"'
fw `" boxWidth: 50,"'
fw `" boxDepth: 100,"'
fw `" light: {"'
fw `" main: {"'
fw `" intensity: 1.2,"'
fw `" shadow: true"'
fw `" },"'
fw `" ambient: {"'
fw `" intensity: 0.3"'
fw `" }"'
fw `" }"'
fw `" },"'
fw `" series: [{"'
fw `" type: 'bar3D',"'
fw `" data: data.map(function (item) {"'
fw `" return {"'
fw `" value: [item[1], item[0], item[2]],"'
fw `" }"'
fw `" }),"'
fw `" shading: 'lambert',"'
fw `" label: {"'
fw `" textStyle: {"'
fw `" fontSize: 16,"'
fw `" borderWidth: 1"'
fw `" }"'
fw `" },"'
fw `" emphasis: {"'
fw `" label: {"'
fw `" textStyle: {"'
fw `" fontSize: 14,"'
fw `" color: '#900'"'
fw `" }"'
fw `" },"'
fw `" itemStyle: {"'
fw `" color: '#900'"'
fw `" }"'
fw `" }"'
fw `" }]"'
fw `"}"'
fw, e t
# Stata

评论

Your browser is out-of-date!

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

×