一次爬方正教务处的成功实践
Contents
[NOTE] Updated January 1, 0001. This article may have outdated content or subject matter.
前戏
不知道从什么时候开始,搞教务处已经成了我山CS专业的学生学习一门新的WEB语言(只要跟web沾边的) Java PHP Python NodeJS Golang….等不同版本就这样一一诞生,当然 我也不例外 这次用golang实现模拟登陆教务处并获取课表 成绩等信息。(额 问我为什么喜欢搞教务处 大概是因为教务处的页面实在太丑了 然后每次都要我去评教 评教的Button ,Chrome竟然不兼容!这么烂的东西,评你【友善度】个【友善度】啊!
入戏
其实 去年自学PHP cURL的时候 我也试过模拟登陆教务处 那时候还做了个查分数的模块挂在微信上(但是人一多真的会炸啊2333 因为那时候服务器还在HK 所以被别人吐槽慢的跟什么一样了) 去年的时候 是看着这篇PHP解决方案来一步步操作的 虽然也遇到了一些问题 但是自己都解决啦~~
我还记得 那篇部落格里有一句话简直就像一个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头
来,我们来看看:
可以 很清楚的看到 不是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就算了 受不起)
Author scnace
LastMod 0001-01-01