前两周,我写了一篇《本科生如何选择毕设》,当我在学校系统上完成课题申报后,留意到了一件事:毕设系统的初始化密码为学号。于是,我当时尝试随机登陆了一位同学的账号,发现能够顺利进入了系统,拿到了他的信息。

我由此猜测大部分学生都比较缺乏安全意识,不会主动去更改密码。好奇心使然,我萌生了一个想法:抓取这届毕业生的毕设信息,进行简单的分析,看看大家到底都在做些什么?只是当时比较忙,没有工夫,暂时搁置了。

今天偶然又想起了这件事,带着交流学习的态度,我决定试一试。原本以为很快就能完成,没想到过程中遇到了一些麻烦,最后花了不少时间。所以说,很多事,纸上谈兵毫不费力,只有亲手实践,才能获得经验的积累。

数据准备

虽然毕设系统的账户密码初始化都是学生的学号,但是我这边并没有全校学生的学号数据。

我第一时间想到的是自己生成,因为各个专业的学号规则都是相似的,我可以先找到这种规律,然后假设一个班有n人,为了避免遗漏,n需要设置得比实际情况大些,比如50,但这一定会产生异常情况,没关系,处理这些异常就足够了。

但我发现这样做不妥,因为有十几个学院,几十种专业,我无法保证自己推测的学号生成规律一定是对的。最好还是能够拿到可靠的数据。通过猜测,我觉得班级QQ群里可能存在相关信息,于是我终于在2016年的群文件里找到了全校的学费缴费款信息表,里面包含了全校1万余名本科生和研究生的学号信息。通过筛选,我拿到了我们19届3000+学生的学号。

模拟登陆与爬虫

我使用Fiddler这个工具抓取了访问毕设系统时发送和接收的数据包,经过分析,我发现登录是这样一个流程:

首先请求登录接口,使用表单携带账号密码;通过验证后,服务端在header中传回cookie信息保存在本地,并生成一个字符串类型的sid来作为用户标识,然后前端带着这些信息去请求首页。

后续的请求通过在header中携带cookie和url中携带sid来完成鉴权,以获得相关数据信息。

整个登录流程就是这样,一点也不复杂,毕竟是学校的教务系统,一般都是外包出去,而且由于年代久远,使用的都是十分老旧和普通的技术,在安全方面也不会有太多的防范措施。

但是由于我已经有段时间没碰爬虫这块,有些生疏,遇到了一个难以解决的问题:无法获取到那个sid。

从服务端传回的数据包里来看,没有这个sid的数据,试验几次后我发现,这个sid不是动态的,那么会不会不是由服务端计算的?直接前端js生成的?但是我又找不到那段js。

这个问题困扰了我好久,始终难以解决,而且渐渐影响了心态。我只好暂时作罢,先平复心情,穆罕默德说:山不过来,我便过去。我想,难道要动用selenium吗?这可是个大家伙,虽然能够专治各种疑难杂症,但是由于是直接模拟实际浏览器行为,效率极其低下。

一般的情况下,它是不会被用于生产的,不过考虑到我这次数据量不大,之前也没有尝试过selenium,于是我向自己妥协了。

在查看文档之后,我尝试写了几段代码(部分,完整源码可在公众号后台回复:「毕设分析」获取),它生效了。

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
def setup():
chromePath = r'C:\Users\casua\Downloads\chromedriver_win32 (1)\chromedriver.exe'
browser = webdriver.Chrome(executable_path=chromePath)
return browser

def login(username, password, browser):
browser.get("http://xxx.edu.cn/index.aspx")
user_btn = browser.find_element_by_id("UserId")
pwd_btn = browser.find_element_by_id("Pwd")
submit_btn = browser.find_element_by_id("LoginButton")
user_btn.send_keys(username)
pwd_btn.send_keys(password)
submit_btn.send_keys(Keys.ENTER)
return browser

def set_sessions(browser):
request = requests.Session()
headers = {
"User-Agent":
"Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 "
"(KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36"
}
request.headers.update(headers)
cookies = browser.get_cookies()
current_url = browser.current_url
for cookie in cookies:
request.cookies.set(cookie['name'], cookie['value'])
return request,current_url

https://v.qq.com/x/page/w1355hgics4.html

由于工具本身的特点以及没有使用多线程,效率比较低,不过selenium还是真香。整个抓取过程大约需要三个小时。 结果显示,寥寥无几的同学修改了密码,我将得到的3300余条数据格式化储存在MySQL中。

局部

分析统计

由于属于刚开题的阶段,信息量不是很足,我利用现有的信息准备从以下几个角度入手:

  1. 各学院毕业人数,男女比例
  2. 学生重名情况
  3. 压力最大的老师
  4. 类别和类型
  5. 各学院毕设题目关键词

各学院毕业人数,男女比例

从结果来看,电信院人丁最为兴旺,工科学校的整体女同学人数是硬伤,只有经管院、公管院、外院是特例,其中外院的男生最有福,材料院的比例完美符合“一对情侣三对基”。

学生重名情况

以下是全校19届学生的重名情况,令我震惊的是,居然没有出现 “张伟”和 “王刚”?杨晨、张旭、陈宇这十二位名列前茅。此外,李嘉琪、陈欣、陈晨、刘彤、曹博、王颖,分别为一男一女,如此有缘,我只能帮你们到这了。

压力最大的老师

从结果来看,韩文民老师居然要带12位同学的毕设,十分辛苦。其余九位压力最大的老师,分别九分辛苦,八分辛苦,七分辛苦…

类别和类型

课题类别方面,”工程设计(实践)”和 “综合”占有绝对的比重,课题性质方面,”模拟性课题”和 “纵向课题”则更受欢迎。各位对号入座吧,我个人选择的类型是:综合,性质是:模拟性课题。

毕设题目关键词

我选择了人数前五的学院来分词,统计词频,生成展示词云。来看看大家毕设都在做些什么吧,排名不分先后:

计算机:

电信:

经管:

船舶:

材料:

可见,隔行如隔山啊,而我由衷感慨:相较于室外工作,写程序能够安坐室内,冬暖夏凉;相比于硬件相关,写程序门槛较底,一台笔记本就能上手入门;相比于实业,互联网的氛围更自由。虽然程序员群体的话题热度一直居高不下,比如“脱发”、“格子衫”等,其实这些大部分都是外界的偏见,要不然怎么现在三百六十行,行行转IT呢?庆幸一入学就接触了软件,此生无悔入IT。

这是我在2018年的最后一篇技术相关的文章,多谢一路相伴,来年还请多多见教,既然彼此遇见,不如砥砺同行。