明天不用比赛之类的了,所以今天晚上也挺闲的,不急着睡。可能也是因为无聊了,就在想怎么样在不知道准考证的情况下查成绩呢,本来好像广东有个按身份证号码查询的,但现在貌似也不管用了。而其他方式只能按准考证号码和姓名来查询。很显然,要想知道成绩,只能一个个的去尝试准考证号码。幸亏准考证号码是挺有规律的,换句话说,我们如果确定了某个学校,那么也就确定了准考证的一段前缀。我们需要枚举的就是课室和座位号了。课室一般不会超过200,座位号一般不会超过40,这个估计应该也挺保守的吧。当然我们可以一个个的尝试,需要的次数也就8000。当然学了计算机,当然要靠计算机的运算能力了,不然自己试会疯掉的。
好了,废话不多说,枚举这个算法很简单,主要问题在于怎么去获取数据。由于目前我会写的,能使用联网的就只有android和php了。android上运行不太放心,所以最后还是用php来写。当然很多东西也没用过,php也现学了一些内容。目前能查分的我知道的就只有2个网站,一个99宿舍,一个学信网。99宿舍查分需要下载一个软件,我没分析这个软件有什么特殊的功能。只是感觉多了个软件,应该难度也更大些。再看看学信网,查询的方式其实就是使用http的get方式,非常容易理解,什么变量什么参数都给你了,非常的明确。之前弄过一些网站,也知道http的get方式是怎么样的一个方式。就比如http://www.chsi.com.cn/cet/query?zkzh=440371121201111&xm=三毛这样一个网址,它有2个参数,一个zkzh,一个是xm,前面那个就是准考证了,后面是名字。所以按理说使用curl来直接获取数据,通过字符串匹配来找到相关信息就可以了。很快就可以弄出下面一个程序来:
$rr='http://www.chsi.com.cn/cet/query?zkzh=4407211212'.$room.$desk.'&xm='.$people;
curl_setopt ($ch, CURLOPT_URL, $rr);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$hao=curl_exec ($ch);
curl_close ($ch);
$ans=strpos($hao, $people);
if ($ans===false) echo $i.' not find '.$people;
else{
echo $rr.' find '.$people;
break;
}
按理说,我按这样的方式传入数据,那么应该就返回相关的内容了。但事实没那么容易,直接访问它的话,它会提示你 “请从 学信网四六级查询 页面进行查询”。 为什么会这样呢。一开始我想到的是cookie,于是利用了chrome的“审查元素”来查看相关的值。不得不说chrome这个工具好强!cookie是有改,但是应该起不来什么作用。然后纠结了很久,转移阵地去查看了headers的信息。终于,发现了个referer。百度了一下,“HTTP Referer是header的一部分,当浏览器向web服务器发送请求的时候,一般会带上Referer,告诉服务器我是从哪个页面链接过来的”。好了有点眉目了,按理说referer并不安全,真正要控制用户只能通过某个页面进行查询的最好方法还是session。不过很幸运的,这个很简单的,在头文件中加一个 Referer:http://www.chsi.com.cn/cet/就搞定了。所以添加的代码是:
curl_setopt ($ch, CURLOPT_REFERER, "http://www.chsi.com.cn/cet/");
之后我们就可以直接根据准考证号和姓名来获取相关信息了。我们要枚举所有可能准考证(按递增的顺序来枚举),然后按准考证和姓名来请求数据,然后进行判断。
最后的结果当然是成功了,我直接获取的准考证号码而已。时间嘛,受制于get请求的很长时间的等待,自然不少。还有很多地方也没优化好,多线程也没做,不然也会快一些。整个程序很简单,都没有打ACM的长。不过今晚学会了挺多东西,包括CURL以及referer。