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

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

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

获取数据

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

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

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

数据处理

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

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
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 数据库之后就能直接运行下面的命令调用该数据集:

Stata
1
cuse jdcourse2018b.dta, c w

一些简单的分析

色块图

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

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
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 为:

Stata
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

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

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

使用 ECharts 绘制三维柱形图

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

# Stata

评论

Your browser is out-of-date!

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

×