教务网的那点事儿


作者:long2ice
时间:2016-06-03


引言


一直对爬虫比较感兴趣,使用php写过一些小爬虫,爬过很多网站,然后收集有用的信息。php的curl库是一个很好用的工具,用来模拟请求爬取网页还是很方便的,使用方法也很简单。然后配上simple_html_dom,一个html的解析插件,一些简单的网页爬取工作就已经可以胜任了。后来发现python更适合来写爬虫,因为python拥有很多强大的库,借用网上的一些话:

  1. python 支持多线程,多进程(fork/deamon);
    2.python有丰富的异步模块、分析模块、爬虫模块以及爬虫相关的资料等等等等;

下面是一个简单的get请求:

  • php使用curl

$ch = curl_init(); curl_setopt($ch,CURLOPT_REFERER,$url); curl_setopt($ch,CURLOPT_URL,$url); curl_setopt($ch,CURLOPT_RETURNTRANSFER,1); $data = curl_exec($ch);

  • python使用requests库

import requests html = requests.get(url) print(html.text)

看起来,python代码比起php的就简洁一些。另外,本文的代码使用的php版本为7.+,python版本为3.5+。

那接下来就进入正题吧。


简介


本文使用php代码完整地讲诉如何一步步模拟登录教务网,然后取得课表等信息,使用python原理其实也都是一样的,只是对应的方法的具体实现不一样。php代码和python代码最后都会在结尾放出来。使用php而不是python的原因是,最初使用php实现登录的,python是后来自己根据php代码的原理移植的,总之原理都是差不多的。另外,这是我第一次在上写文章,介于水平有限,有错之处还望指正。


正文


这应该是最重要的一步了。我们知道,成功登录教务网后肯定是会返回一个cookie的,我们要做的就是,成功登录教务网,然后储存返回的cookie,再利用这个cookie去访问其他的链接。只要正确地得到了这个cookie,那就成功一大半了。下面就是详细地步骤:
1. 获取登录url
首先,打开谷歌浏览器,进入教务网首页,F12打开开发者工具,勾上Preserve log防止链接跳转找不到;然后输入正确的学号密码,于是成功得到了登录url:

教务网的那点事儿_第1张图片

2. 获取请求参数:

教务网的那点事儿_第2张图片

其中,最重要的前五个参数和最后一个参数,然后最难的就是获取第一个,第二个,以及最后一个参数了,下面就一一讲解每个参数的获取。

既然是通过表单提交的,又不是我们自己输入的,那就右键打开查看网页源代码吧。
于是乎找了半天,什么鬼,居然没找到?想了想,直接用get请求一下登录链接,然后把返回数据写入html文件中,找到里面的form标签,可以看到所有的参数都在里面,其中重要的代码:
,这就是那一串非常长非常蛋疼的参数,先放着,继续找;
第二个参数也找到了;
,最后一个找是找到了,但是我要的value呢?这...
在最初的时候,这里困扰了我很长一段时间,导致我一直无法成功地登录,直到后来灵机一动,好吧,其实是听室友,成功模拟登录了的,说这是经过加密了参数。然后我突然醒悟了过来,于是,与教务网的斗争继续。
前端加密无非就是js了,寻找js,然后搜索有关“efdfdfuuyyuuckjg”的代码。按照这个思路,终于找了了其加密函数。其实就在返回的html数据中。其中有这么一段js代码:
function chkpwd(obj) { var schoolcode = "10611"; var yhm = document.all.txt_dsdsdsdjkjkjc.value; if (obj.value != "") { if (document.all.Sel_Type.value == "ADM") yhm = yhm.toUpperCase(); var s = md5(yhm + md5(obj.value).substring(0, 30).toUpperCase() + schoolcode).substring(0, 30).toUpperCase(); document.all.efdfdfuuyyuuckjg.value = s; } else { document.all.efdfdfuuyyuuckjg.value = obj.value; } }
结合表单中的
,最后一个参数也就显而易见了。js加密过程如下:
1)将密码md5加密,然后截取前30个字符,并且变成大写字母;
2)将学号与第一步得到的字符串拼接,再与固定参数拼接,然后将整个字符串md5加密,截取前30个字母并且转为大写,就得到了加密过后的字符串,也就是input的value值。
既然得到了加密过程,那用php代码就很好实现了,代码如下:
function checkPwd($code, $pwd, $schoolcode) { return strtoupper(substr(md5(($code . strtoupper(substr(md5($pwd), 0, 30)) . $schoolcode)), 0, 30)); }
而第一个和第二个参数直接正则匹配出来就行了,代码如下:
function getView() { $url = $this->login_url; $result = $this->get($url); $pattern = '//is'; preg_match_all($pattern, $result, $matches); $res[0] = $matches[1][0]; $pattern = '//is'; preg_match_all($pattern, $result, $matches); $res[1] = $matches[1][0]; return $res; }
返回的数组就是两个参数的值。

3、请求结果

这样我们所有的参数都得到了,直接post带参数,得到返回数据,代码如下:
function post($url, $post_data) { $this->cookie = dirname(__FILE__) . '\cookie_edu.txt'; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); curl_setopt($ch, CURLOPT_COOKIEJAR, $this->cookie); curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post_data)); $result = curl_exec($ch); curl_close($ch); return $result; }

教务网的那点事儿_第3张图片
返回html界面

OK,登录成功。而且cookie我们也保存下来了。
那么在我们检测是否成功登录的时候,使用strpos函数检测返回的字符串中是否含有“正在加载权限数据”字符串就可以了,该函数返回出现该字符串的位置,若没有待检测字符串返回-1。

既然得到了cookie就好办了,直接抓取如成绩查询的url然后携带cookie去请求就行了,不管是get或者post都是可以的。比如get:
function get($url) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); curl_setopt($ch, CURLOPT_COOKIEFILE, $this->cookie); $result = curl_exec($ch); return $result; }
试着抓取一下考试安排:


得到了下面的页面,注意这些url都可以F12抓包得到的,其它如获取成绩啊什么道理也是一样的,只要找到url,携带好cookie请求就可以了。


结语


整个过程基本就是这样了,其实有关模拟登陆步骤都是差不多的,只不过有的可能有验证码,有的加密过程更加复杂,比如腾讯的登陆加密过程实现是相当复杂,以前研究过不久就望而却步了。不过网上还是有大牛弄出来的。所以学习实在是无止境的,而自己要学的东西还有很多很多。

仓库地址:https://github.com/long2ice/edu.git

博客地址:https://blog.long2ice.cn

你可能感兴趣的:(教务网的那点事儿)