手把手帶你打造一個教務(wù)系統(tǒng)客戶端(附源碼)

本篇博客主要和大家分享編寫一個學(xué)校教務(wù)系統(tǒng)的客戶端版本哩至,主要是關(guān)于登錄以及數(shù)據(jù)獲取方面,結(jié)尾還會附上本人以前編寫的客戶端源代碼辜妓,有興趣的可以自行下載玩耍~
閱讀本文大概需要5分鐘罗洗。

前言

好久沒有更新博客了,最近有點忙个曙。今天對之前在學(xué)校做的一個項目開源,并以正方教務(wù)系統(tǒng)為例受楼,分享下如何抓取教務(wù)系統(tǒng)的數(shù)據(jù)~ 好了廢話不多說直接開始垦搬。

分析

搭建一個App,首先離不開的肯定就是數(shù)據(jù)艳汽,在通常情況下猴贰,App的數(shù)據(jù)都是由服務(wù)器提供的接口返回的,但是一般來說河狐,學(xué)校都是不會把數(shù)據(jù)以及服務(wù)器提供給學(xué)生的米绕,所以就要采取一些非正常手段。我們知道馋艺,網(wǎng)頁是由瀏覽器解析html代碼后展現(xiàn)出來的栅干,那么只要我們拿到html代碼,自己抓取html里我們所需要的數(shù)據(jù)捐祠,就能完成對數(shù)據(jù)的獲取了碱鳞。
這里我使用的是一個能方便處理html文本的java庫Jsoup,對于它的具體用法可以參考我之前的文章《Android利用Jsoup抓取數(shù)據(jù)踱蛀,再也不怕寫App沒有數(shù)據(jù)啦》窿给,這里就不再贅述了。

登錄

Cookie保存

通常我們使用瀏覽器去訪問我們的教務(wù)系統(tǒng)的時候率拒,服務(wù)器都是通過cookie來對我們當(dāng)前的狀態(tài)進(jìn)行判斷以便獲取我們的登錄狀態(tài)崩泡,那么為了能讓我們的登錄狀態(tài)得以持續(xù),以便我們后續(xù)對其他數(shù)據(jù)的抓取猬膨,我們在客戶端中需要對cookie進(jìn)行一下存儲角撞。

因為我采用的是OkHttp來作為網(wǎng)絡(luò)請求,所以這里以O(shè)kHttp為例

OkHttpClient okHttpClient = new OkHttpClient.Builder().
                connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS).
                readTimeout(READ_TIMEOUT, TimeUnit.SECONDS).
                writeTimeout(WRITE_TIMEOUT, TimeUnit.SECONDS).
                cookieJar(new OkHttpCookieJar()).  
                build();
public class OkHttpCookieJar implements CookieJar {
    private Map<String, List<Cookie>> cookieStore = new HashMap<>();

    @Override
    public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
        cookieStore.put(url.host(), cookies);
    }

    @Override
    public List<Cookie> loadForRequest(HttpUrl url) {
        List<Cookie> cookies = cookieStore.get(url.host());
        return cookies != null ? cookies : new ArrayList<Cookie>();
    }
}

這里我只將其存入到了一個map中,并沒有對cookie進(jìn)行持久化存儲(比如通過SharedPreferences)等等靴寂,所以意味著每次重新打開客戶端都需要登錄一遍磷蜀,大家可以根據(jù)自己的需求進(jìn)行改造。

模擬登錄

首先我們需要先抓取到登錄的接口百炬,以Chrome為例褐隆,按F12打開開發(fā)者工具,然后選擇Network剖踊,勾選Preserve log庶弃。

DevTools

然后進(jìn)行一次正常的登錄,就可以抓取到登錄的url以及請求頭德澈,表單數(shù)據(jù)等等(圖片對一些敏感數(shù)據(jù)做了處理)歇攻。

登錄

可以看到請求頭以及表單所需要的內(nèi)容,根據(jù)你所填的賬號密碼驗證碼等等梆造,很快就能判斷出對應(yīng)的key缴守,以我之前學(xué)校為例的話,TextBox1對應(yīng)賬號镇辉,TextBox2對應(yīng)密碼屡穗,TextBox3對應(yīng)驗證碼,RadioButtonList1就是身份了忽肛,然后你肯定發(fā)現(xiàn)了村砂,_VIEWSTATE是什么鬼,因為這個正方教務(wù)系統(tǒng)是用Asp.net寫的屹逛,那個_VIEWSTATE就是.net的础废,這里我們不探究它到底做啥用的,據(jù)我觀察罕模,這個值并不是永遠(yuǎn)不變的评腺,所以這里我們肯定是要在每次登錄的時候獲取它并把它放到表單里,那從哪里獲取它呢手销。還是一樣歇僧,F(xiàn)12然后查看登錄頁面的html源碼图张,

html

可以發(fā)現(xiàn)這個_VIEWSTATE的變量值就存在于form表單中锋拖,那么一切都很簡單了,先獲取一次登錄頁面祸轮,拿到了_VIEWSTATE的值之后兽埃,在登錄的時候?qū)⑦@個值一起post上去就可以了。即為拿到登錄頁面的html源碼适袜,使用Jsoup篩選出需要的值柄错,然后登錄的時候一并post上去

String __VIEWSTATE = Jsoup.parse(html).select("input[name='__VIEWSTATE']").val();

這里不再贅述Jsoup的具體用法,可以參考我之前的文章。以O(shè)kHttp為例售貌,附上簡單的登錄代碼

 RequestBody requestBody = new MultipartBody.Builder().
                addFormDataPart("__VIEWSTATE", __VIEWSTATE ).
                addFormDataPart("TextBox1", username).
                addFormDataPart("TextBox2", password).
                addFormDataPart("TextBox3", verificationCode).
                addFormDataPart("Button1", "").
                addFormDataPart("RadioButtonList1", "學(xué)生").build();
        Request request = new Request.Builder().url(loginUrl).post(requestBody).build();
        okHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {

            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {

            }
        });

整個登錄流程如下


登錄

關(guān)于驗證碼给猾,這里要補充一點,即請求驗證碼圖片的cookie要和你登錄的時候一致颂跨,驗證碼才能通過敢伸,從代碼角度來說,以O(shè)kHttp為例恒削,你需要用同一個OkHttp對象去完成請求驗證碼以及登錄等等(就是不要new 兩個對象啦)~

抓取數(shù)據(jù)

登錄成功后池颈,我們現(xiàn)在已經(jīng)能夠拿到各個模塊的數(shù)據(jù)了,那么一切都好辦了钓丰。具體怎么拿這里以獲取課表為例躯砰,同理其他的獲取成績等等均是這個思路

首頁

正方教務(wù)系統(tǒng)的首頁一般都是這個樣子的,我們老規(guī)矩携丁,F(xiàn)12查看一下html源碼

html

可以看到琢歇,各個模塊的url均能拿到,老規(guī)矩梦鉴,直接拿到源碼矿微,Jsoup解析一下

        Map<String, String> urlMap = new HashMap<>();
        Document document = Jsoup.parse(html);
        Elements elements = document.select("ul.nav li.top ul.sub li a");
        for (Element element : elements) {
            String value = "教務(wù)網(wǎng)的host" + "/" + element.attr("href").toString();
            String key = element.text();
            urlMap.put(key, value);
        }
        return urlMap;

這里我直接保存到map集合中,因為html中的url是在同個域下的尚揣,所以抓取出來的url是不包含域名的涌矢,這里我們手動把它拼上就可以了,現(xiàn)在我們拿到對應(yīng)模塊的url快骗,還是老套路娜庇,按照所需要的參數(shù)進(jìn)行訪問,拿到html源碼

html

按照規(guī)則使用Jsoup進(jìn)行解析就行了方篮,這里就不再贅述了名秀,最后效果如下

demo

總結(jié)

因為篇幅問題,所以本文難以很細(xì)致的講清楚整個項目的每個細(xì)節(jié)藕溅,只能大概的將整個思路分享出來匕得,如果有興趣的也可以自行clone源碼進(jìn)行查看,為了方便大家查看demo的效果巾表,我在demo里已經(jīng)放入了一些html靜態(tài)頁面汁掠,不用賬號密碼即可直接登錄
源碼地址:教務(wù)管理系統(tǒng)

關(guān)于快速替換為自己學(xué)校的教務(wù)系統(tǒng)

如果你學(xué)校的教務(wù)系統(tǒng)也是正方集币,那么這里提供一下比較快速的替換方法考阱,但可能由于css樣式等差異,具體可能還是需要微調(diào)鞠苟,就需要你根據(jù)你學(xué)校教務(wù)系統(tǒng)的html源碼進(jìn)行調(diào)整了乞榨。
1.首先秽之,CommonUtils.java中的isDemo改為false

public class CommonUtils {
    public static boolean isDemo = true; // 改為false
    ....
}

2.將/app/src/main/res/values/api.xml下的url替換為你學(xué)校對應(yīng)的url

3.運行App,看哪里解析有問題吃既,針對你學(xué)校教務(wù)系統(tǒng)的html代碼考榨,根據(jù)css樣式等差異進(jìn)行微調(diào)。


如果覺得對你有所幫助鹦倚,請點個贊董虱,謝謝。你的鼓勵是我最大的動力申鱼。
歡迎關(guān)注EoniJJ的簡書

不定期與你分享關(guān)于Android開發(fā)的點點滴滴愤诱。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市捐友,隨后出現(xiàn)的幾起案子淫半,更是在濱河造成了極大的恐慌,老刑警劉巖匣砖,帶你破解...
    沈念sama閱讀 206,602評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件科吭,死亡現(xiàn)場離奇詭異,居然都是意外死亡猴鲫,警方通過查閱死者的電腦和手機对人,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來拂共,“玉大人牺弄,你說我怎么就攤上這事∫撕” “怎么了势告?”我有些...
    開封第一講書人閱讀 152,878評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長抚恒。 經(jīng)常有香客問我咱台,道長,這世上最難降的妖魔是什么俭驮? 我笑而不...
    開封第一講書人閱讀 55,306評論 1 279
  • 正文 為了忘掉前任回溺,我火速辦了婚禮,結(jié)果婚禮上混萝,老公的妹妹穿的比我還像新娘遗遵。我一直安慰自己,他們只是感情好譬圣,可當(dāng)我...
    茶點故事閱讀 64,330評論 5 373
  • 文/花漫 我一把揭開白布瓮恭。 她就那樣靜靜地躺著雄坪,像睡著了一般厘熟。 火紅的嫁衣襯著肌膚如雪屯蹦。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,071評論 1 285
  • 那天绳姨,我揣著相機與錄音登澜,去河邊找鬼。 笑死飘庄,一個胖子當(dāng)著我的面吹牛脑蠕,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播跪削,決...
    沈念sama閱讀 38,382評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼谴仙,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了碾盐?” 一聲冷哼從身側(cè)響起晃跺,我...
    開封第一講書人閱讀 37,006評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎毫玖,沒想到半個月后掀虎,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,512評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡付枫,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,965評論 2 325
  • 正文 我和宋清朗相戀三年烹玉,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片阐滩。...
    茶點故事閱讀 38,094評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡二打,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出掂榔,到底是詐尸還是另有隱情址儒,我是刑警寧澤,帶...
    沈念sama閱讀 33,732評論 4 323
  • 正文 年R本政府宣布衅疙,位于F島的核電站莲趣,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏饱溢。R本人自食惡果不足惜喧伞,卻給世界環(huán)境...
    茶點故事閱讀 39,283評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望绩郎。 院中可真熱鬧潘鲫,春花似錦、人聲如沸肋杖。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽状植。三九已至浊竟,卻和暖如春怨喘,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背振定。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評論 1 262
  • 我被黑心中介騙來泰國打工必怜, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人后频。 一個月前我還...
    沈念sama閱讀 45,536評論 2 354
  • 正文 我出身青樓梳庆,卻偏偏與公主長得像,于是被迫代替她去往敵國和親卑惜。 傳聞我的和親對象是個殘疾皇子膏执,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,828評論 2 345

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,515評論 25 707
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)露久,斷路器胧后,智...
    卡卡羅2017閱讀 134,600評論 18 139
  • 前言 在Android開發(fā)中,網(wǎng)絡(luò)請求十分常用 而在Android網(wǎng)絡(luò)請求庫中抱环,Retrofit是當(dāng)下最熱的一個網(wǎng)...
    Carson帶你學(xué)安卓閱讀 70,612評論 48 393
  • 二零一七 來到三月 不知不覺 已沒太多 結(jié)束傀儡的歲月進(jìn)入自己的春天 富足的墮落的思考著 今天的明天的時間呢 我沒...
    騎著小車聽音樂閱讀 307評論 0 1
  • 沿著公路上的白線壳快,躲過地上的井蓋,耳邊聽著人造風(fēng)镇草。10月2日早上七點零幾分眶痰,我騎著電車前往老董的住處,那天我們計劃...
    和規(guī)則決裂閱讀 504評論 0 1