HttpClient + Jsoup模拟登录教务处并获取课表

  

1、概述

  最近想做一个校园助手类的APP,由于第一次做,所以打算先把每个功能单独实现,防止乱了阵脚。利用教务处登录获取课表和成绩等是一个基本功能,所以以获取课表为例实现了这个功能。完整代码点这里,尝试了好几次的,所以写的比较乱

2、涉及的关键知识

  首先,明确获取课表的流程:其实,获取课表就是让手机模拟浏览器,给服务器传去账号、密码,然后服务器会返回cookies(不懂自行百度),利用cookie就可以穿梭自如了,比如查课表。但是,浏览器登录时,返回的html文件浏览器是会自动解析成网页展现在我们面前的,但是APP就不行了,所以需要我们自己从html字符流中解析出我们需要的信息。就我自己的情况来看,模拟登录花了不少时间(这方面很不熟),解析html很快就解决了(可能是之前实践偶解析JSON)。

  这样一个APP主要涉及到3个重要知识点:

1、如何模拟登录:java有自己的HttpURLConnection,但是不够灵活,所以用 apache的HttpClient更方便

2、如何解析HTML:网上查一下,Jsoup很合适。

3、AsyncTask:显然获取网页并解析是不能再主线程进行的,所以需要使用异步任务。

4、回调函数:这个不是必须的,但是我为了降低程序耦合度把网络请求那部分单独成了一个类,这时候更新主UI就需要利用回调函数了,之后细说

3、模拟登陆(以窝工UPR为例)

  1、解析教务处登录界面,看到一些教程用的还是HttpWatch,确实过时了,显然直接Google浏览器F12就行了。如下图,选择Network

HttpClient + Jsoup模拟登录教务处并获取课表_第1张图片

  点一下登录,就可以看到一大堆信息,我们需要的是第一个:

HttpClient + Jsoup模拟登录教务处并获取课表_第2张图片

 

  点击就可以看到详细信息了:

HttpClient + Jsoup模拟登录教务处并获取课表_第3张图片

  重要的有两个,Cookie,拿到这个我们才能导出去访问,Form Data就是模拟登录时要提交(POST)的表单数据;

4、HTML解析

利用上一步模拟登录拿到的Cookie就可以去获取课表了,同理,需要解析网页,如下,点击我的课表

HttpClient + Jsoup模拟登录教务处并获取课表_第4张图片

 

  可以看到一大堆信息,找到需要的

HttpClient + Jsoup模拟登录教务处并获取课表_第5张图片

  这个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{
 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 list = new ArrayList();
 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 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 131            132              133              135              137              139              141              143              145              147            148            149              151              152              154              155              156              158              160              161              162            163              164              166              167              168              170              172              173              174            175              176              177              179              180              182              183              184              185            186              187              188              190              191              193              194              195              196              197                201              202            
203            204              206              207              209              211              212              214              215              216              217            218              219              221              223              224              226              227              228              229            230              231              233              234              235              236              238              239              240            241              242              244              245              246              247              249              250              251              252                256              257            
258            259              261              262              264              266              267              268              269              270              271            272              273              275              277              278              279              280              281              282            283              284              286              288              289              290              291              292              293            294              295              296              297              298              299              300              301              302          
  134
星期一
136
星期二
138
星期三
140
星期四
142
星期五
144
星期六
146
星期日
  150

上午

第1节(08:00-08:45)   计算机网络A_01(西部校区综合教学2号楼B406) 153
          编译原理_01(校部综合教学1号楼综151) 157
  计算机组成原理_01(西部校区综合教学2号楼B103) 159
       
第2节(08:50-09:35)   计算机网络A_01(西部校区综合教学2号楼B406) 165
          编译原理_01(校部综合教学1号楼综151) 169
  计算机组成原理_01(西部校区综合教学2号楼B103) 171
       
第3节(10:05-10:50)       面向对象程序设计_01(西部校区综合教学2号楼A301) 178
      人工智能_01(西部校区综合教学2号楼A101) 181
           
第4节(10:55-11:40)       面向对象程序设计_01(西部校区综合教学2号楼A301) 189
      人工智能_01(西部校区综合教学2号楼A101) 192
           
  198

199 午 休

200
  205

下午

第5节(13:30-14:15)   编译原理_01(校部综合教学1号楼综151) 208
  计算机组成原理_01(西部校区综合教学2号楼B103) 210
      计算机网络A_01(西部校区综合教学2号楼B406) 213
           
第6节(14:20-15:05)   编译原理_01(校部综合教学1号楼综151) 220
  计算机组成原理_01(西部校区综合教学2号楼B103) 222
      计算机网络A_01(西部校区综合教学2号楼B406) 225
           
第7节(15:35-16:20)   人工智能_01(西部校区综合教学2号楼A101) 232
              面向对象程序设计_01(西部校区综合教学2号楼A301) 237
       
第8节(16:25-17:10)   人工智能_01(西部校区综合教学2号楼A101) 243
              面向对象程序设计_01(西部校区综合教学2号楼A301) 248
       
  253

254 晚 饭

255
  260

晚上

第9节(18:00-18:45)   社会学*_886(校部综合教学1号楼综152) 263
  人类文明史*_887(校部材料馆材101) 265
                   
第10节(18:55-19:40)   社会学*_886(校部综合教学1号楼综152) 274
  人类文明史*_887(校部材料馆材101) 276
                   
第11节(19:50-20:35)   社会学*_886(校部综合教学1号楼综152) 285
  人类文明史*_887(校部材料馆材101) 287
                   
第12节(20:45-21:30)                            
303 304 */
View Code

 

5、关于回调函数的使用

  这一部分之前完全没预料到,只是后来才发现,不用内部类,想更新UI就得用回调函数,其更深层次的思想是一种设计模式,还是自己学的太少!知识使用完全浮于表面。

6、Demo演示

HttpClient + Jsoup模拟登录教务处并获取课表_第6张图片

7、总结

  零零散散花了不少时间,一来确实第一次做类似工作,二来自己习惯非常不好,对于新工具,研究API和即学即用能力不强。明天应该好好研究一下HttpClientJsoup,达到熟练抓取各种网页的目的!毕竟这只是开始!现在的学习状态实在太低效了。

  以上。

转载于:https://www.cnblogs.com/zhaoyu1995/p/5875577.html

你可能感兴趣的:(HttpClient + Jsoup模拟登录教务处并获取课表)