這是在博客園里開博以來寫的第一篇博客。
因為之前看過很多人都有發過關於模擬登錄正方軟件獲取數據的文章,自己覺得挺好玩的便也去動手一做,開始還以為挺難的,但實際做起來還蠻簡單的,當然其中還有些小插曲。
廢話不多說,先po兩張效果圖:


界面做得比較隨意,有空會再完善的。
接下來便說說是如何實現的了。
首先,你得有個抓包工具(其實用瀏覽器自帶的f12工具應該也是可以的,就是比較麻煩),很多人都是用Httpwatch(貌似支持IE跟火狐),這里我就隨波逐流,也用Httpwatch。安裝好Httpwatch之后便可以直接打開瀏覽器登錄教務系統抓包啦

在點擊登錄按鈕的時候記得先點擊記錄。
登錄進去之后便可以看到Httpwatch中有數據變化了。

這時先選中方法為Post的這一行(記下此時的URL,后面有用到),再選中Post數據來看看要提交的表單有哪些。

這里面我們只要用到上面圈出的五個參數。
第一個參數“_VIEWSTATE”要自己獲得(獲取登錄首頁的html內容然后在里面提取就行了);
第二個參數RadioButtonList1的亂碼數值其實是“學生”(有的Httpwatch版本可以顯示,有的則是亂碼),提交表單時提交“學生”即可;
第三個參數TextBox2是密碼;
第四個參數txtSecretCode是登錄界面的驗證碼,有的學校系統可以直接繞過,我學校的則不行(開始看了別人的說可以直接填空寫死,結果在這里被坑了好久,最后只能老老實實把驗證碼加上去),所以具體可不可以還得自己試試;
第五個參數是學號;
(每個學校提交的參數應該都是不同的,不過依葫蘆畫瓢就行了)
其實表單中還有一個更重要的參數:Cookie

Cookie的值在每一次提交的時候都得加上去,Cookie同“_VIEWSTATE”一樣得自己先獲得,不過不一樣的是Cookie獲取一次就可以,但“_VIEWSTATE”必須每次提交都得獲取一次。
現在就來提交表單嘗試登錄
String URL = "http://jwgl.gdut.edu.cn/default2.aspx";//上面說到的URL HttpPost mHttpPost = new HttpPost(URL);//建立連接 mHttpPost.getParams().setParameter(ClientPNames.HANDLE_REDIRECTS, false);//禁止重定向 mHttpPost.setHeader("Cookie", Cookie);//設置Cookie //填寫表單 List<NameValuePair> list = new ArrayList<NameValuePair>(); list.add(new BasicNameValuePair("__VIEWSTATE",viewstate)); list.add(new BasicNameValuePair("txtUserName",學號)); list.add(new BasicNameValuePair("TextBox2", 密碼)); list.add(new BasicNameValuePair("RadioButtonList1","學生")); list.add(new BasicNameValuePair("txtSecretCode", 驗證碼)); //下面幾個都直接填空寫死即可(事實上下面幾個只需添加Button1即可) list.add(new BasicNameValuePair("Button1", "")); list.add(new BasicNameValuePair("lbLanguage", "")); list.add(new BasicNameValuePair("hidPdrs", "")); list.add(new BasicNameValuePair("hidsc", "")); mHttpPost.setEntity(new UrlEncodedFormEntity(list, "GBK"));//提交表單 HttpResponse mHttpResponse = new DefaultHttpClient().execute(mHttpPost);// 響應請求 int statusCode = mHttpResponse.getStatusLine().getStatusCode();//狀態碼若為200則表示登錄失敗,此時需檢查是否表單有誤;若狀態碼為302則表示成功
當上述狀態碼為302時可繼續往下,若為200請繼續檢查測試。
實際上要用到的地址是剛剛302下面的跳轉的地址

我們再來對它建立連接嘗試登錄
String URL = "http://jwgl.gdut.edu.cn/xs_main.aspx?xh=" + 學號; HttpPost mHttpPost = new HttpPost(URL);//這里用post跟get都可以 //這里要比上次多添加一個值“Referer”,即將它的值置為此時的URL地址 mHttpPost.setHeader("Referer", URL); mHttpPost.setHeader("Cookie", Cookie);//Cookie還是原來的值 HttpResponse mHttpResponse = new DefaultHttpClient().execute(mHttpPost);//響應請求 //此時的狀態碼若為200則表示成功登錄進入教務系統 if (httpResponse.getStatusLine().getStatusCode() == 200) { HttpEntity mHttpEntity = mHttpResponse.getEntity(); String html = EntityUtils.toString(mHttpEntity);//獲取網頁內容 String studentName = Jsoup.parse(html).getElementById("xhxm").text();//獲取學生名字,后面查詢成績時需要用到 }
登錄成功之后再回到瀏覽器先把剛剛抓取的數據清空,再重新點擊記錄,再進行成績的查詢,便可以抓取到數據了

同樣我們找到方法為Post的這一行,選中它,同時記下它的URL,同樣再在下面選中Post數據來看看需要提交的表單

這時我們需要提交的參數有上面四個,
第一個參數“_VIEWSTATE”同樣需要自己重新獲得(注意,這里的參數已經跟上面的不一樣了,此時應該獲取的是登錄成功后的頁面的html內容,然后再提取即可);
第二個參數Button1又亂碼了,實際上是剛剛三個按鈕的值
第三個參數ddlXN是學年;
第四個參數ddlXQ是學期;
(在這里如果點擊按學期查詢,那么就必須提交第三個跟第四個參數;如果點擊按學年查詢,那么就必須提交第三個參數;如果點擊在校學習成績查詢,那么第三個跟第四個參數都不用提交,所以我們可以在代碼中加個判斷)
接下來我們用已有的參數來建立連接:
String URL = "http://jwgl.gdut.edu.cn/xscj.aspx?xh=" + 學號 + "&xm=" + 學生姓名 + "&gnmkdm=N121605";//學生姓名就是上面獲取到的studentName HttpPost mHttpPost = new HttpPost(URL); //填寫表單 List<NameValuePair> list= new ArrayList<NameValuePair>(); list.add(new BasicNameValuePair("__VIEWSTATE", viewstate)); list.add(new BasicNameValuePair("Button1", "按學期查詢"));//這里我用學期查詢,因此需要添加下面兩個參數 list.add(new BasicNameValuePair("ddlXN", "2014-2015")); list.add(new BasicNameValuePair("ddlXQ", "1")); mHttpPost.setEntity(new UrlEncodedFormEntity(params, "GBK"));//提交表單 //這里我們同樣需要設置兩個頭信息。后面的套路跟前面的是差不多的 mHttpPost.setHeader("Referer", "http://jwgl.gdut.edu.cn/xs_main.aspx?xh=" + 學號); mHttpPost.setHeader("Cookie", Cookie); HttpResponse mHttpResponse = new DefaultHttpClient().execute(mHttpPost); HttpEntity mHttpEntity = mHttpResponse.getEntity(); String html = EntityUtils.toString(mHttpEntity);//此時就獲取到含有成績信息的頁面了 //用Jsoup將里面的課程成績提取出來 Elements mElements = Jsoup.parse(html).select("td"); //再根據需要向mElements中提取需要的數據,再將其添加到listview中就大功告成了
當然,實現了成績查詢,其他的功能像什么課表查詢、考試查詢也都可以一一實現了,原理都是差不多的。
