最近很多人问我到底怎么模拟登陆正方系统来抓取课表和成绩的,其实如果你知道了浏览器是怎么和服务器交互数据的话,实现起来就很简单了。
当我们输入学号、密码后点击登陆,浏览器会把我们的学号、密码或者验证码,post到服务器的一个地址,服务器接受到POST请求后,首先验证验证码是否正确,然后验证学号、密码是否正确,如果其中有一个不正确的话,直接返回验证码错误或者学号不存在或者密码错误。如果匹配正确,那么服务器会生成随机串(就是SessionId)来表示登陆成功的状态,并返回给浏览器,浏览器得到这个串之后,作为cookies保存在浏览器,每次要获取登陆后里面的数据时都会提交这个串来验证是否已经登陆。好吧,大概的流程差不多就是这样了。所以我们需要做的就是来模拟浏览器的行为,获取登陆成功后的验证串,并通过它来请求成绩、课表的数据。
怎么模拟浏览器的行为?这个我在PHP中使用CURL实现GET和POST请求里面讲的很清楚了,请大家先把这篇博文看完。
好了,我们已经知道怎么去模拟浏览器行为了,那我们就来看看登陆的时候浏览器到底做了些什么?我们使用HTTP抓包工具Fiddler来对登陆的过程进行抓包,当然其他工具也是可以的,像httpclient或者直接使用浏览器的F12开发者工具。下面是我们对登陆抓包的结果:
首先我们看到txtUserName是我们填写的学号、TextBox2是我们填写的密码、txtSecreCode是我们填写的验证码、RadioButtonList1是我们选择的登陆身份。
那__VIEWSTATE和__VIEWSTATEGENERATOR又是啥玩意儿?
既然在这里提交了,那肯定不是凭空产生的,我们来看看登陆界面的源码:
小样,以为隐藏了我就看不到你了?
所以我们要先获取到这两个隐藏表单的值。怎么获取?使用正则表达式匹配即可。在这里我先不对正则表达式进行详细的讲解。
我们把获取这两个值的方法写到一个方法里面:
1 2 3 4 5 6 7 8 9 10 11 12 | public function getView(){ $res; $url = 'http://220.168.44.238/default2.aspx'; $result = $this->curl_request($url); $pattern = '/<input type="hidden" name="__VIEWSTATE" value="(.*?)" \/>/is'; preg_match_all($pattern, $result, $matches); $res[0] = $matches[1][0]; $pattern = '/<input type="hidden" name="__VIEWSTATEGENERATOR" value="(.*?)" \/>/is'; preg_match_all($pattern, $result, $matches); $res[1] = $matches[1][0]; return $res; } |
好了,我们来看看获取的结果:
好了,这两个值搞定!!!
下面所有的POST数据都准备了,只需要我们POST提交即可!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | function login(){ $url = '登陆页面地址'; $post['__VIEWSTATE'] = 上面获取结果; $post['__VIEWSTATEGENERATOR'] = 上面获取结果; $post['txtUserName'] = 学号; $post['TextBox2'] = 密码; $post['txtSecretCode'] = ''; $post['lbLanguage'] = ''; $post['RadioButtonList1'] = iconv('utf-8', 'gb2312', '学生'); $post['Button1'] = iconv('utf-8', 'gb2312', '登录'); $result = $this->curl_request($url,$post,'', 1); print_r($result); return $result; } |
我们来看看登陆结果,这次我们的主要目的就是获取登陆成功后的验证串(也就是cookies),表示我们已经登陆成功了!
然后,记得保存好这个cookies!!!!
哎,,,等一下,别忽悠大家!!!说的验证码怎么是空的???劳资研究了半年怎么获取验证码图片上面的文字,你TM啥都没填就行了?这个。。。我给大家解释一下。
首先验证码是怎么生成的?
当我们去访问登陆界面的时候,页面里会有一个获取验证码的地址,然后浏览器再去服务器请求验证码的图片,服务器收到验证码图片的请求,并在服务器生成一个随机串,然后把这个随机串生成成一张图片,再返回给浏览器,所以就看到了所谓的验证码。。。如果我们不去请求这个生成验证码图片的地址?我们手动来try一try!!!
首先我们找到这个生成验证码图片的地址,然后把这个地址加到屏蔽规则里面,这样浏览器就不会去访问这个地址了。(是不是很机智?哈哈、、、)
我们再来访问登陆界面,,,好了验证码图片不见了,,,,但是是不是真的不用填就能登陆呢?试试不就知道了吗?
再点击登陆呢?真不好意思,我们就这么登进去了。。。。哈哈。。。
为什么会这样?因为你没有去请求验证码图片,服务器也就不会给你生成验证码,所以提交的时候,你提交空的验证码,服务器后台也空的验证码,刚好吻合,我TM太机智了。。。好吧,这只是正方,如果在服务器后台加一个判断,如果验证码为空,直接返回登陆失败了!!!黑线!!!GG 了。。。
好了,扯了这么多我们来看看用代码能不能访问到后台的主页?
1 2 3 | $url = '后台主页地址/xs_main.aspx?xh='.$this->studentId; $result = $this->curl_request($url,'',$this->cookie); //我们保存的cookies print_r($result); |
登陆进来了!!!这下什么成绩、课表、什么的都不是问题了。。。
先来看看课表~~
我们直接GET获取课表的URL就行了。。。。
1 2 3 | $url = "后台主页地址/xskbcx.aspx?xh=".$this->studentId; $result = $this->curl_request($url,'',$this->cookie); print_r($result); |
至于成绩,我们还得POST几个其他数据,抓包先!!!我们点历年成绩。
上面两个字段和登陆一样,不解释。。。
1 2 3 4 5 6 7 8 | $url = "后台主页地址/xscjcx.aspx?xh=".$this->studentId; $post['ddl_kcxz'] = ''; $post['btn_zcj'] = iconv('utf-8', 'gb2312', '历年成绩'); $post['__VIEWSTATE'] = 抓取结果; $post['__VIEWSTATEGENERATOR'] = 抓取结果; $result = $this->curl_request($url,$post,$this->cookie); $result = iconv('gbk', 'utf-8', $result); print_r($result); |
抓取结果如下:
完了。。。。。暴露本学渣智商了。。。。。QAQ~~~
好了,成绩、课表都抓取完了。。。。至于其它的什么信息,原理都是一样的。。。其它网站也是,大家可发挥各自的聪明才智来整出好玩的东西来。。。
下面是我以前做的一个微信平台成绩、课表的查询示意图。。。因为快要找工作了,这个平台也没怎么管理了,哎~~~到时让学弟学妹来管理吧。
公众平台微信号:csufter
个人微信号:xiaoqing28
Permalink
我在我们学校的正方教务系统中使用了但是返回的结果是null
Permalink
先获取cookies的值,然后模拟登陆获取后台主界面试试。只要提交的参数没问题,肯定能成功的。
Permalink
能把你演示所用的代码文件发我吗?我直接Copy你那些代码有些函数缺了
Permalink
关键的代码我都给上了,要是直接给你个源码,我写这个也没啥意义了。
Permalink
我已经把Viewstate的值换了我们学校的教务系统对应值,然后登陆页面地址也换了,但是就登陆时就返回这样的信息:
Authentication of viewstate failed. 1) If this is a cluster, edit configuration so all servers use the same validationKey and validation algorithm. AutoGenerate cannot be used in a cluster. 2) Viewstate can only be posted back to the same page. 3) The viewstate for this page might be corrupted.
Permalink
异常信息: System.Web.HttpException: Authentication of viewstate failed. 1) If this is a cluster, edit configuration so all servers use the same validationKey and validation algorithm. AutoGenerate cannot be used in a cluster. 2) Viewstate can only be posted back to the same page. 3) The viewstate for this page might be corrupted.
[HttpException (0x80004005): Invalid_Viewstate
Client IP: 172.16.1.17
Port: 55136
User-Agent: SAE/fetchurl-w23n122lom
ViewState: dDw3OTkxMjIwNTU7Oz6wnfZQpvPtwubwZ+/mbxvVhowzIg==
Http-Referer: http://服务器IP地址/xs_main.aspx?xh=我的学号
Permalink
亲,可以指导一下我正方验证码的问题么?看了你的博客好不是很懂
Permalink
验证码填空
Permalink
那个获取__VIEWSTATE的值,我用CURL做的,为什么返回不了__VIEWSTATE的值。返回的数array为空。
Permalink
首先,看页面有没有这个值,然后看你正则表达式写的对不对。
Permalink
我查询成绩那块出了问题,我发现我的__VIEWSTATE变了,抓包出来的,我提取出来了,然后照着抓包工具把__VIEWSTATE提交上去,按学期查询 按学年查询 。。。。打印 我抓包抓不到任何中文字,这是抓到的值然后我用抓包工具得到的地址。post出去但是给我返回上面几个文字。
Permalink
__VIEWSTATE这个值是你动态获取的,不是手动填的。
Permalink
行了,可以查到了,你知道怎么样能得到平时成绩吗?这个好像是隐藏的。
Permalink
大哥,我用的虚拟主机不能添加屏蔽规则,验证码怎么办呢,你用的是哪个主机
Permalink
我在上面说的添加屏蔽规则只是为了证明我们可以不必请求验证码,直接提交,所以你在代码里直接把验证码填空即可。
Permalink
我的登陆后查询课表和成绩怎么都会出现Object moved to here.
Permalink
这是你提交的参数有问题。
Permalink
异常详细信息: System.ArgumentException: 回发或回调参数无效。在配置中使用 或在页面中使用 启用了事件验证。出于安全目的,此功能验证回发或回调事件的参数是否来源于最初呈现这些事件的服务器控件。如果数据有效并且是预期的,则使用 ClientScriptManager.RegisterForEventValidation 方法来注册回发或回调数据以进行验证。
源错误:
执行当前 Web 请求期间生成了未经处理的异常。可以使用下面的异常堆栈跟踪信息确定有关异常原因和发生位置的信息。
堆栈跟踪:
[ArgumentException: 回发或回调参数无效。在配置中使用 或在页面中使用 启用了事件验证。出于安全目的,此功能验证回发或回调事件的参数是否来源于最初呈现这些事件的服务器控件。如果数据有效并且是预期的,则使用 ClientScriptManager.RegisterForEventValidation 方法来注册回发或回调数据以进行验证。]
System.Web.UI.ClientScriptManager.ValidateEvent(String uniqueId, String argument) +144
System.Web.UI.Control.ValidateEvent(String uniqueID, String eventArgument) +111
System.Web.UI.WebControls.TextBox.LoadPostData(String postDataKey, NameValueCollection postCollection) +26
System.Web.UI.WebControls.TextBox.System.Web.UI.IPostBackDataHandler.LoadPostData(String postDataKey, NameValueCollection postCollection) +13
System.Web.UI.Page.ProcessPostData(NameValueCollection postData, Boolean fBeforeLoad) +303
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1819
版本信息: Microsoft .NET Framework 版本:4.0.30319; ASP.NET 版本:4.0.30319.17626 )
这个事什么原因?
Permalink
这个是C#写的吗? C#我不是太熟悉。你可以跟踪下是哪里出错了,是不是提交的参数name的问题呢?
Permalink
php写的
Permalink
你提交的路径有误,禁止从站点外部提交数据
这又是为什么
Permalink
设置Referer为你要提交的站点。
Permalink
能登陆进去,但是不知道怎么登到课表界面
Permalink
可以把登录到课表页面的详细点吗?我直接把网址弄成http://jwjx.njit.edu.cn/xskbcx.aspx?xh=我的学号&xm=我的名字&gnmkdm=N121603(课表地址),这样出来的是Object moved to here,这是为什么呢?
Permalink
网址写http://jwjx.njit.edu.cn/xskbcx.aspx?xh=我的学号 就可以了。然后记得加上cookies提交。
Permalink
要提交的cookie是先保存在本地再提取,还是直接函数引用?我直接调用能登陆到主界面,但是再登到课表界面就无法显示了。(登陆课表使用的cookie是登陆主界面前使用的,还是登陆到主界面重新要获得cookie?)
Permalink
已经解决了,谢谢博主。
Permalink
怎么解决的啊?我的也出现了Object move here。同是获取课表时候的问题,连url都一样xskbcx.aspx?xh=我的学号&xm=我的名字&gnmkdm=N121603(课表地址)。求教
Permalink
楼主我这边出现了Object moved to here,不知道是什么原因,可以获取cookies
Permalink
大神,我们学校的教务系统怎么获取不到cookies了?
能看看嘛?是我们学校的问题还是系统的问题?
http://zf.hhit.edu.cn
Permalink
大神可否赐教?我试过了就是不行啊。。。
Permalink
可以加群交流~
Permalink
求群号
Permalink
同样是object moved here的问题啊,求楼主解答
Permalink
这种都是cookies的问题,看看cookie有没有保存,再对比下提交的字段。
Permalink
但是可以登陆进去啊,登陆进去再操作就不行了
Permalink
找到群了啊哈哈
Permalink
ERROR – 出错啦!
错误原因:系统正忙!
请重新登陆,如无法解决,请稍后再试
我的cookie保存了,也没啥问题,但登录上去就显示这个。。怎么弄的啊
Permalink
这是系统的问题吧
Permalink
你这个问题解决了吗
Permalink
小白一只。。。求群号交流下
Permalink
找到了
Permalink
好文,特来顶楼主,最近想用c#实现它,有没有什么方式能和lz交流?想请教一些问题
Permalink
右上方有群可以加入~
Permalink
博主,按照你的方法能够登录到教务系统并能查课表,但是成绩出不来,不知道是不是正则表达式(我用的就是上面登录时候_匹配_VIEWSTATE的正则表达式)的问题。。。望求指教!
Permalink
可以先不正则匹配,看能否获取到成绩页面。
Permalink
你好。我之前第一次获取的时候都可以用。。然后再登的时候就不行了。。代码都差不多,没有办法获取cookie 是有什么限制吗
Permalink
还是object move to here。 提交的东西有误?我也是直接从浏览器复制,为什么响应表头还是302。另外我们学校的教务系统只能内网访问,怎么解决?
Permalink
http://222.17.128.21/(xxxxxxxxxxxxxxxxxx)/default_ysdx.aspx 这个尝试登录失败,提交表单之后返回的是登陆的界面,改一下xxxxx的值用火狐里面的重发也不行,求博主帮助~
Permalink
$url = ‘http://61.142.33.204/xskbcx.aspx?xh=’.$id.’&xm=’.$name.’&gnmkdm=N121603′;
$result =curl_request($url,”,$urlcookie);
print_r($result);
返回一个Object moved to here. 怎么破,而且,好像不能直接get获取课表和成绩
Permalink
curl_request()这个方法是你自己写的吗?我的出错了
Permalink
同样Object moved to here. 只要是通过get 方式后面参数带有xm的都是Object moved to here.如果是参数错误 会不会是xm发送过去的编码问题?
Permalink
博主,用curl函数抓取只有__VIEWSTATE这个隐藏字段,提交上去经常报上面的错,然后我写了循环,发现还是要很久才能抓到课表的内容。。
Permalink
curl_request()这个方法是你自己写的吧?
Permalink
cookie是如何保存的?
Permalink
能求源码吗 新手不太懂
Permalink
不知楼主还能看到不,我最近也在做微信平台方面查询成绩的功能,很感谢您的教程,我基本做好了,不过有个小问题想问您下,就是如果某个用户查询成绩的时候我们给他返回一个结果,这个结果是之前我们用一个脚本爬下来存储好 还是用户发请求的同时去爬取呢?那样子会不会太慢了?我的策略是用户发请求才去爬取,然后先缓存下来,这段时间内给用户返回的都是缓存,隔一定的时间之后如果用户再发请求的话重新爬取。您觉得这样可以不?会不会太慢了?
Permalink
能否给份源码学习学习
Permalink
Fatal error: Using $this when not in object context
这是不兼容php5嘛?