前戏

不知道从什么时候开始,搞教务处已经成了我山CS专业的学生学习一门新的WEB语言(只要跟web沾边的)  Java PHP Python NodeJS Golang….等不同版本就这样一一诞生,当然 我也不例外 这次用golang实现模拟登陆教务处并获取课表 成绩等信息。(额  问我为什么喜欢搞教务处  大概是因为教务处的页面实在太丑了 然后每次都要我去评教 评教的Button ,Chrome竟然不兼容!这么烂的东西,评你【友善度】个【友善度】啊!

入戏

其实 去年自学PHP cURL的时候 我也试过模拟登陆教务处  那时候还做了个查分数的模块挂在微信上(但是人一多真的会炸啊2333  因为那时候服务器还在HK 所以被别人吐槽慢的跟什么一样了)    去年的时候 是看着这篇PHP解决方案来一步步操作的 虽然也遇到了一些问题 但是自己都解决啦~~

我还记得 那篇部落格里有一句话简直就像一个Flag一样 插在了那里  我当时看的时候就觉得药丸,药丸。。。。

然后。。。

然后。。。

然后。。。

flag

正方的程序猿肯定也看到了这篇部落格(嗯 肯定是这样!)

怪不得 寒假老是接到小伙伴的反馈 说我的东西崩掉了(原来真的是这样)

所以,还是用**通用办法(我连验证码一起抓还不行吗!)**吧。。

HOW TO DO

我尽量说一下通用步骤:

STEP 1

请求还是要发的,第一步要去教务处的Login界面 去拿VIEWSTATE 和 VIEWSTATEGENERATOR,这两货我就不多说了,之前的链接里面有说明。还多了一步,就是这个操作也要拿下Cookie(STEP2要用到)

STEP 2

竟然验证码已经绕不过去了 那我们就不绕了。我们通过F12检查发现 验证码也是有地址的(./CheckCode.aspx),我们把Step1拿到的cookies带上去发Get请求到这个地址,不要废话,拿了Body体就走,然后把body里面的gif缓存在本地。这边给下示范:

    // 获取验证码
    var verify_code string
    for {
    //用刚才生成的cookie去爬 验证码   否则会504!!!!!

       res, _ = c.Do(req)      
       file, _ := os.Create("verify.gif")
       io.Copy(file, res.Body)

      fmt.Println("请查看verify.gif, 然后输入验证码, 看不清输入0重新获取验证码")
       fmt.Scanf("%s", &verify_code)
       if verify_code != "0" {
           break
       }

当然 我用了带break的while(true){}循环  憋说了 已经因为l1不分被嘲笑了无数次了(泪)

STEP3:

在STEP2确认测试通过的前提下,也就是本地存在了那张gif图片(测试的时候gif图片我是用ie打开的,因为读写要尽可能分离),接下来就是比较重要的post环节了,其实上面那篇php的实现里面已经写得很详细了,我这边由于是golang版本的,golang 1.5 新加了跟python一样的cookiejar .Client带cookiejar实现抓取实在是太爽了,蛤蛤蛤。。哦,对了,强调一点,由于这破JWC看起来像是上世纪的产物,所以,不要忘了把你的utf-8转成gbk2312哦,这个是个坑,勿入~

golang的话 可以考虑一下这个库

"github.com/scbizu/mahonia"

当然 七牛的库也不错

"github.com/qiniu/iconv"

其他的lang乃们就自己找吧(吐舌头~

这里我也贴个代码吧~

    /**
    *模拟post表单
    */
    func post(Rurl string,c *http.Client,username string,password string,verify_code string,VIEWSTATE string,VIEWSTATEGENERATOR string,temp_cookies []*http.Cookie) []*http.Cookie{
        postValue:=url.Values{}
        cd:=mahonia.NewEncoder("gb2312")
        rb:=cd.ConvertString("学生")
        //准备POST的数据
        postValue.Add("txtUserName",username)
        postValue.Add("TextBox2",password)
        postValue.Add("txtSecretCode",verify_code)
        postValue.Add("__VIEWSTATE",VIEWSTATE)
        postValue.Add("__VIEWSTATEGENERATOR",VIEWSTATEGENERATOR)
        postValue.Add("Button1","")
        postValue.Add("lbLanguage","")
        postValue.Add("hidPdrs","")
        postValue.Add("hidsc","")
        postValue.Add("RadioButtonList1",rb)
        //开始POST   这次POST到登陆界面   带上第一次请求的cookie 和 验证码  和 一些必要的数据
        postUrl,_:=url.Parse(Rurl)
        Jar,_:=cookiejar.New(nil)
        Jar.SetCookies(postUrl,temp_cookies)
        c.Jar=Jar   
        resp,_:=c.PostForm(Rurl,postValue)
        cookies:=resp.Cookies()
        return cookies
        }

STEP4:

看到这里说明你已经快接近成功了。

拿着上面登陆成功的cookie去登陆成功的页面(./xs_main.aspx?xh=YOUR STUDENT No.)看看 是否能出现意料之中的body 没有的话  再仔细检查一下自己的STEP3 慢慢来 不要急 喝杯水 继续呗~

成功了的话 也不要以为JWC就是任你行了 Naive 还是有坑的。。。

如果 有一定web基础的同学**肯定按下了F12 然后打开个人课表。**没错,所以你看到了下面的页面其实都是假象() 真正的页面只有点了Network的人才会明白 。

没错 就是它(./xskbcx.aspx?xh=YOUR STUDENT No.&xm=urlencode(YOUR NAME)&gnmkdm=N121603)

其实,老司机告诉你,其实xm和gnmkdm都是可选的get set value 你只要get上去你自己的xh就可以了

Like this : ./xskbcx.aspx?xh=YOUR STUDENT No

STEP5:

如果泥还看下去,说明你遇到问题了 是不是发现Get上去了 却response给了你302啊 嘿嘿嘿  就是这个神奇的302的,

这时候查看header里的Location还是空,是不是感觉整个人都要崩溃了,我在这里也懵逼了一个晚上+一个上午

直到……..

一个苹果掉在了我的头上。。。。

怎么可能  我又不是牛顿。。。

我偶然间 对比了两次request头

来,我们来看看:

norefer  hasrefer

可以 很清楚的看到 不是cookie的锅(把你的光标从post函数上离开)

200的尝试  有referer头!

就是因为这个重定向头 导致你一直302;

此时 仿佛中了500w一般开心吧~

知道了这个梗 我们在Request里面设置一个重定向:

Like this:

      req.Header.Set("Referer",courseURL)

STEP 6:

好了 JWC可以任你行了 去玩吧~ Enjoy your time,guys!

END

最后 贴上源码地址:https://github.com/scbizu/Zafu_jwcInterface

萌新  弱弱地求一发Follow(Star就算了  受不起)