最近想作一個校園助手類的APP,因爲第一次作,因此打算先把每一個功能單獨實現,防止亂了陣腳。利用教務處登陸獲取課表和成績等是一個基本功能,因此以獲取課表爲例實現了這個功能。完整代碼點這裏,嘗試了好幾回的,因此寫的比較亂。html
首先,明確獲取課表的流程:其實,獲取課表就是讓手機模擬瀏覽器,給服務器傳去帳號、密碼,而後服務器會返回cookies(不懂自行百度),利用cookie就能夠穿梭自如了,好比查課表。可是,瀏覽器登陸時,返回的html文件瀏覽器是會自動解析成網頁展示在咱們面前的,可是APP就不行了,因此須要咱們本身從html字符流中解析出咱們須要的信息。就我本身的狀況來看,模擬登陸花了很多時間(這方面很不熟),解析html很快就解決了(多是以前實踐偶解析JSON)。java
這樣一個APP主要涉及到3個重要知識點:node
一、如何模擬登陸:java有本身的HttpURLConnection,可是不夠靈活,因此用 apache的HttpClient更方便android
二、如何解析HTML:網上查一下,Jsoup很合適。web
三、AsyncTask:顯然獲取網頁並解析是不能再主線程進行的,因此須要使用異步任務。apache
四、回調函數:這個不是必須的,可是我爲了下降程序耦合度把網絡請求那部分單獨成了一個類,這時候更新主UI就須要利用回調函數了,以後細說。設計模式
一、解析教務處登陸界面,看到一些教程用的仍是HttpWatch,確實過期了,顯然直接Google瀏覽器F12就好了。以下圖,選擇Network瀏覽器
點一下登陸,就能夠看到一大堆信息,咱們須要的是第一個:服務器
點擊就能夠看到詳細信息了:cookie
重要的有兩個,Cookie,拿到這個咱們才能導出去訪問,Form Data就是模擬登陸時要提交(POST)的表單數據;
利用上一步模擬登陸拿到的Cookie就能夠去獲取課表了,同理,須要解析網頁,以下,點擊個人課表
能夠看到一大堆信息,找到須要的
這個Response就是會返回咱們的字符流,咱們須要的就是解析它,設計到Jsoup的詳細使用就不細說了,本身也是今天才接觸,
總之藉助以上兩步就能夠寫出主要類Login.java的代碼了,以下:
1 package com.example.upr.net; 2 3 import java.io.BufferedReader; 4 import java.io.IOException; 5 import java.io.InputStream; 6 import java.io.InputStreamReader; 7 import java.io.UnsupportedEncodingException; 8 import java.util.ArrayList; 9 import java.util.List; 10 11 import org.apache.http.HttpEntity; 12 import org.apache.http.HttpResponse; 13 import org.apache.http.NameValuePair; 14 import org.apache.http.client.ClientProtocolException; 15 import org.apache.http.client.HttpClient; 16 import org.apache.http.client.entity.UrlEncodedFormEntity; 17 import org.apache.http.client.methods.HttpGet; 18 import org.apache.http.client.methods.HttpPost; 19 import org.apache.http.cookie.Cookie; 20 import org.apache.http.impl.client.AbstractHttpClient; 21 import org.apache.http.impl.client.DefaultHttpClient; 22 import org.apache.http.message.BasicNameValuePair; 23 import org.jsoup.Jsoup; 24 import org.jsoup.nodes.Document; 25 import org.jsoup.nodes.Element; 26 import org.jsoup.select.Elements; 27 28 import com.example.upr.CompleteListener; 29 30 import android.R.integer; 31 import android.os.AsyncTask; 32 import android.provider.ContactsContract.Contacts.Data; 33 import android.util.Log; 34 import android.widget.Toast; 35 36 public class Login extends AsyncTask<Void, Void, String[][]>{ 37 38 private String zjh; 39 private String mm; 40 private String webPage; 41 private String [][] kebiao = new String[15][8]; 42 private CompleteListener listener; 43 public Login(String account, String password, CompleteListener listener) { 44 zjh = account; 45 mm = password; 46 47 this.listener = listener; 48 } 49 @Override 50 protected String[][] doInBackground(Void... arg0) { 51 List<NameValuePair> list = new ArrayList<NameValuePair>(); 52 list.add(new BasicNameValuePair("zjh", zjh)); 53 list.add(new BasicNameValuePair("mm", mm));//表單信息 54 String encode = "gb2312";//編碼格式,從F12工具中能夠找到 55 HttpClient httpClient = new DefaultHttpClient(); 56 List<Cookie> cookies; 57 try { 58 HttpEntity entity = new UrlEncodedFormEntity(list ,encode);//封裝數據 59 HttpPost post = new HttpPost(com.example.upr.Constant.LOGIN_URL);//創建POST請求 60 post.setEntity(entity); 61 HttpResponse httpResponse = httpClient.execute(post); 62 String data, result; 63 if (httpResponse.getStatusLine().getStatusCode() == 200) {//登陸成功 64 cookies = ((AbstractHttpClient) httpClient).getCookieStore().getCookies();//獲取Cookie 65 HttpGet httpGet = new HttpGet("http://zhjw.dlut.edu.cn/xkAction.do?actionType=6"); 66 httpGet.setHeader("Cookie", "JSESSIONID="+ cookies.get(0).getValue()+";"+ 67 "NSC_kjbpxv-iuuq="+cookies.get(1).getValue());//注意分號 68 httpResponse = new DefaultHttpClient().execute(httpGet); 69 70 StringBuffer sb = new StringBuffer(); 71 entity = httpResponse.getEntity(); 72 InputStream inputStream = entity.getContent(); 73 BufferedReader br = new BufferedReader(new InputStreamReader(inputStream, encode)); 74 while ((data = br.readLine()) != null) { 75 sb.append(data); //讀取返回的網頁 76 } 77 result = sb.toString(); 78 webPage = result; 79 80 } else { 81 return null; 82 } 83 } catch (UnsupportedEncodingException e) { 84 e.printStackTrace(); 85 return null; 86 } catch (ClientProtocolException e) { 87 // TODO Auto-generated catch block 88 e.printStackTrace(); 89 return null; 90 } catch (IOException e) { 91 // TODO Auto-generated catch block 92 e.printStackTrace(); 93 return null; 94 } 95 96 Document document = Jsoup.parse(webPage); 97 if (document != null) { 98 Element element = document.getElementById("user");//經過id直接定位到數據 99 Elements trElements = element.select("tr"); 100 //如下是提取課表信息,每一個網站不一樣,一下代碼要解析的html放在最下面了 101 for (int i = 0; i < trElements.size(); i++) { 102 Elements tdElements = trElements.get(i).select("td"); 103 for (int j = 0; j < tdElements.size(); j++) { 104 String text = tdElements.get(j).text(); 105 if (tdElements.size() == 1) { 106 continue; 107 } else if (tdElements.size()==9) { 108 if (j != 0) { 109 kebiao[i][j-1] = text; 110 } 111 }else { 112 kebiao[i][j] = text; 113 } 114 115 } 116 } 117 return kebiao; 118 } else { 119 return null; 120 } 121 122 } 123 @Override 124 protected void onPostExecute(String[][] result) { 125 super.onPostExecute(result); 126 listener.onConnectFinish(result);//執行回調函數,更新主UI 127 } 128 } 129 /* 130 <table cellpadding="0" width="100%" class="displayTag" cellspacing="0" border="1" id="user"> 131 <tr> 132 <td colspan="2" class="sortable"> </td> 133 <td width="13%" class="sortable"> 134 <div align="center">星期一</div></td> 135 <td width="13%" class="sortable"> 136 <div align="center">星期二</div></td> 137 <td width="13%" class="sortable"> 138 <div align="center">星期三</div></td> 139 <td width="13%" class="sortable"> 140 <div align="center">星期四</div></td> 141 <td width="13%" class="sortable"> 142 <div align="center">星期五</div></td> 143 <td width="13%" class="sortable"> 144 <div align="center">星期六</div></td> 145 <td width="13%" class="sortable"> 146 <div align="center">星期日</div></td> 147 </tr> 148 <tr bgcolor="#FFFFFF"> 149 <td width="3%" rowspan="4"> 150 <p class="style4">上午</p></td> 151 <td width="11%">第1節(08:00-08:45)</td> 152 <td> 計算機網絡A_01(西部校區綜合教學2號樓B406) 153 <br></td> 154 <td> </td> 155 <td> </td> 156 <td> 編譯原理_01(校部綜合教學1號樓綜151) 157 <br></td> 158 <td> 計算機組成原理_01(西部校區綜合教學2號樓B103) 159 <br></td> 160 <td> </td> 161 <td> </td></tr> 162 <tr bgcolor="#FFFFFF"> 163 <td width="11%">第2節(08:50-09:35)</td> 164 <td> 計算機網絡A_01(西部校區綜合教學2號樓B406) 165 <br></td> 166 <td> </td> 167 <td> </td> 168 <td> 編譯原理_01(校部綜合教學1號樓綜151) 169 <br></td> 170 <td> 計算機組成原理_01(西部校區綜合教學2號樓B103) 171 <br></td> 172 <td> </td> 173 <td> </td></tr> 174 <tr bgcolor="#FFFFFF"> 175 <td width="11%">第3節(10:05-10:50)</td> 176 <td> </td> 177 <td> 面向對象程序設計_01(西部校區綜合教學2號樓A301) 178 <br></td> 179 <td> </td> 180 <td> 人工智能_01(西部校區綜合教學2號樓A101) 181 <br></td> 182 <td> </td> 183 <td> </td> 184 <td> </td></tr> 185 <tr bgcolor="#FFFFFF"> 186 <td width="11%">第4節(10:55-11:40)</td> 187 <td> </td> 188 <td> 面向對象程序設計_01(西部校區綜合教學2號樓A301) 189 <br></td> 190 <td> </td> 191 <td> 人工智能_01(西部校區綜合教學2號樓A101) 192 <br></td> 193 <td> </td> 194 <td> </td> 195 <td> </td> 196 <tr bgcolor="#FFFFFF"> 197 <td colspan="9"> 198 <p align="center" class="td2 style5"> 199 <strong>午 休</strong></p> 200 </td> 201 </tr> 202 </tr> 203 <tr bgcolor="#FFFFFF"> 204 <td width="3%" rowspan="4"> 205 <p class="style4">下午</p></td> 206 <td width="11%">第5節(13:30-14:15)</td> 207 <td> 編譯原理_01(校部綜合教學1號樓綜151) 208 <br></td> 209 <td> 計算機組成原理_01(西部校區綜合教學2號樓B103) 210 <br></td> 211 <td> </td> 212 <td> 計算機網絡A_01(西部校區綜合教學2號樓B406) 213 <br></td> 214 <td> </td> 215 <td> </td> 216 <td> </td></tr> 217 <tr bgcolor="#FFFFFF"> 218 <td width="11%">第6節(14:20-15:05)</td> 219 <td> 編譯原理_01(校部綜合教學1號樓綜151) 220 <br></td> 221 <td> 計算機組成原理_01(西部校區綜合教學2號樓B103) 222 <br></td> 223 <td> </td> 224 <td> 計算機網絡A_01(西部校區綜合教學2號樓B406) 225 <br></td> 226 <td> </td> 227 <td> </td> 228 <td> </td></tr> 229 <tr bgcolor="#FFFFFF"> 230 <td width="11%">第7節(15:35-16:20)</td> 231 <td> 人工智能_01(西部校區綜合教學2號樓A101) 232 <br></td> 233 <td> </td> 234 <td> </td> 235 <td> </td> 236 <td> 面向對象程序設計_01(西部校區綜合教學2號樓A301) 237 <br></td> 238 <td> </td> 239 <td> </td></tr> 240 <tr bgcolor="#FFFFFF"> 241 <td width="11%">第8節(16:25-17:10)</td> 242 <td> 人工智能_01(西部校區綜合教學2號樓A101) 243 <br></td> 244 <td> </td> 245 <td> </td> 246 <td> </td> 247 <td> 面向對象程序設計_01(西部校區綜合教學2號樓A301) 248 <br></td> 249 <td> </td> 250 <td> </td> 251 <tr bgcolor="#FFFFFF"> 252 <td colspan="9"> 253 <p align="center" class="td2 style5"> 254 <strong>晚 飯</strong></p> 255 </td> 256 </tr> 257 </tr> 258 <tr bgcolor="#FFFFFF"> 259 <td width="3%" rowspan="4"> 260 <p class="style4">晚上</p></td> 261 <td width="11%">第9節(18:00-18:45)</td> 262 <td> 社會學*_886(校部綜合教學1號樓綜152) 263 <br></td> 264 <td> 人類文明史*_887(校部材料館材101) 265 <br></td> 266 <td> </td> 267 <td> </td> 268 <td> </td> 269 <td> </td> 270 <td> </td></tr> 271 <tr bgcolor="#FFFFFF"> 272 <td width="11%">第10節(18:55-19:40)</td> 273 <td> 社會學*_886(校部綜合教學1號樓綜152) 274 <br></td> 275 <td> 人類文明史*_887(校部材料館材101) 276 <br></td> 277 <td> </td> 278 <td> </td> 279 <td> </td> 280 <td> </td> 281 <td> </td></tr> 282 <tr bgcolor="#FFFFFF"> 283 <td width="11%">第11節(19:50-20:35)</td> 284 <td> 社會學*_886(校部綜合教學1號樓綜152) 285 <br></td> 286 <td> 人類文明史*_887(校部材料館材101) 287 <br></td> 288 <td> </td> 289 <td> </td> 290 <td> </td> 291 <td> </td> 292 <td> </td></tr> 293 <tr bgcolor="#FFFFFF"> 294 <td width="11%">第12節(20:45-21:30)</td> 295 <td> </td> 296 <td> </td> 297 <td> </td> 298 <td> </td> 299 <td> </td> 300 <td> </td> 301 <td> </td></tr> 302 </table> 303 304 */
這一部分以前徹底沒預料到,只是後來才發現,不用內部類,想更新UI就得用回調函數,其更深層次的思想是一種設計模式,仍是本身學的太少!知識使用徹底浮於表面。
零零散散花了很多時間,一來確實第一次作相似工做,二來本身習慣很是很差,對於新工具,研究API和即學即用能力不強。明天應該好好研究一下HttpClient和Jsoup,達到熟練抓取各類網頁的目的!畢竟這只是開始!如今的學習狀態實在過低效了。
以上。