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

2023-10-14 17:10

本文主要是介绍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

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

 

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

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

4、HTML解析

利用上一步模拟登录拿到的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">&nbsp;</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">&nbsp;
150                 <p class="style4">上午</p></td>
151               <td width="11%">第1节(08:00-08:45)</td>
152               <td>&nbsp; 计算机网络A_01(西部校区综合教学2号楼B406)
153                 <br></td>
154               <td>&nbsp; &nbsp;</td>
155               <td>&nbsp; &nbsp;</td>
156               <td>&nbsp; 编译原理_01(校部综合教学1号楼综151)
157                 <br></td>
158               <td>&nbsp; 计算机组成原理_01(西部校区综合教学2号楼B103)
159                 <br></td>
160               <td>&nbsp; &nbsp;</td>
161               <td>&nbsp; &nbsp;</td></tr>
162             <tr bgcolor="#FFFFFF">
163               <td width="11%">第2节(08:50-09:35)</td>
164               <td>&nbsp; 计算机网络A_01(西部校区综合教学2号楼B406)
165                 <br></td>
166               <td>&nbsp; &nbsp;</td>
167               <td>&nbsp; &nbsp;</td>
168               <td>&nbsp; 编译原理_01(校部综合教学1号楼综151)
169                 <br></td>
170               <td>&nbsp; 计算机组成原理_01(西部校区综合教学2号楼B103)
171                 <br></td>
172               <td>&nbsp; &nbsp;</td>
173               <td>&nbsp; &nbsp;</td></tr>
174             <tr bgcolor="#FFFFFF">
175               <td width="11%">第3节(10:05-10:50)</td>
176               <td>&nbsp; &nbsp;</td>
177               <td>&nbsp; 面向对象程序设计_01(西部校区综合教学2号楼A301)
178                 <br></td>
179               <td>&nbsp; &nbsp;</td>
180               <td>&nbsp; 人工智能_01(西部校区综合教学2号楼A101)
181                 <br></td>
182               <td>&nbsp; &nbsp;</td>
183               <td>&nbsp; &nbsp;</td>
184               <td>&nbsp; &nbsp;</td></tr>
185             <tr bgcolor="#FFFFFF">
186               <td width="11%">第4节(10:55-11:40)</td>
187               <td>&nbsp; &nbsp;</td>
188               <td>&nbsp; 面向对象程序设计_01(西部校区综合教学2号楼A301)
189                 <br></td>
190               <td>&nbsp; &nbsp;</td>
191               <td>&nbsp; 人工智能_01(西部校区综合教学2号楼A101)
192                 <br></td>
193               <td>&nbsp; &nbsp;</td>
194               <td>&nbsp; &nbsp;</td>
195               <td>&nbsp; &nbsp;</td>
196               <tr bgcolor="#FFFFFF">
197                 <td colspan="9">&nbsp;
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">&nbsp;
205                 <p class="style4">下午</p></td>
206               <td width="11%">第5节(13:30-14:15)</td>
207               <td>&nbsp; 编译原理_01(校部综合教学1号楼综151)
208                 <br></td>
209               <td>&nbsp; 计算机组成原理_01(西部校区综合教学2号楼B103)
210                 <br></td>
211               <td>&nbsp; &nbsp;</td>
212               <td>&nbsp; 计算机网络A_01(西部校区综合教学2号楼B406)
213                 <br></td>
214               <td>&nbsp; &nbsp;</td>
215               <td>&nbsp; &nbsp;</td>
216               <td>&nbsp; &nbsp;</td></tr>
217             <tr bgcolor="#FFFFFF">
218               <td width="11%">第6节(14:20-15:05)</td>
219               <td>&nbsp; 编译原理_01(校部综合教学1号楼综151)
220                 <br></td>
221               <td>&nbsp; 计算机组成原理_01(西部校区综合教学2号楼B103)
222                 <br></td>
223               <td>&nbsp; &nbsp;</td>
224               <td>&nbsp; 计算机网络A_01(西部校区综合教学2号楼B406)
225                 <br></td>
226               <td>&nbsp; &nbsp;</td>
227               <td>&nbsp; &nbsp;</td>
228               <td>&nbsp; &nbsp;</td></tr>
229             <tr bgcolor="#FFFFFF">
230               <td width="11%">第7节(15:35-16:20)</td>
231               <td>&nbsp; 人工智能_01(西部校区综合教学2号楼A101)
232                 <br></td>
233               <td>&nbsp; &nbsp;</td>
234               <td>&nbsp; &nbsp;</td>
235               <td>&nbsp; &nbsp;</td>
236               <td>&nbsp; 面向对象程序设计_01(西部校区综合教学2号楼A301)
237                 <br></td>
238               <td>&nbsp; &nbsp;</td>
239               <td>&nbsp; &nbsp;</td></tr>
240             <tr bgcolor="#FFFFFF">
241               <td width="11%">第8节(16:25-17:10)</td>
242               <td>&nbsp; 人工智能_01(西部校区综合教学2号楼A101)
243                 <br></td>
244               <td>&nbsp; &nbsp;</td>
245               <td>&nbsp; &nbsp;</td>
246               <td>&nbsp; &nbsp;</td>
247               <td>&nbsp; 面向对象程序设计_01(西部校区综合教学2号楼A301)
248                 <br></td>
249               <td>&nbsp; &nbsp;</td>
250               <td>&nbsp; &nbsp;</td>
251               <tr bgcolor="#FFFFFF">
252                 <td colspan="9">&nbsp;
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">&nbsp;
260                 <p class="style4">晚上</p></td>
261               <td width="11%">第9节(18:00-18:45)</td>
262               <td>&nbsp; 社会学*_886(校部综合教学1号楼综152)
263                 <br></td>
264               <td>&nbsp; 人类文明史*_887(校部材料馆材101)
265                 <br></td>
266               <td>&nbsp; &nbsp;</td>
267               <td>&nbsp; &nbsp;</td>
268               <td>&nbsp; &nbsp;</td>
269               <td>&nbsp; &nbsp;</td>
270               <td>&nbsp; &nbsp;</td></tr>
271             <tr bgcolor="#FFFFFF">
272               <td width="11%">第10节(18:55-19:40)</td>
273               <td>&nbsp; 社会学*_886(校部综合教学1号楼综152)
274                 <br></td>
275               <td>&nbsp; 人类文明史*_887(校部材料馆材101)
276                 <br></td>
277               <td>&nbsp; &nbsp;</td>
278               <td>&nbsp; &nbsp;</td>
279               <td>&nbsp; &nbsp;</td>
280               <td>&nbsp; &nbsp;</td>
281               <td>&nbsp; &nbsp;</td></tr>
282             <tr bgcolor="#FFFFFF">
283               <td width="11%">第11节(19:50-20:35)</td>
284               <td>&nbsp; 社会学*_886(校部综合教学1号楼综152)
285                 <br></td>
286               <td>&nbsp; 人类文明史*_887(校部材料馆材101)
287                 <br></td>
288               <td>&nbsp; &nbsp;</td>
289               <td>&nbsp; &nbsp;</td>
290               <td>&nbsp; &nbsp;</td>
291               <td>&nbsp; &nbsp;</td>
292               <td>&nbsp; &nbsp;</td></tr>
293             <tr bgcolor="#FFFFFF">
294               <td width="11%">第12节(20:45-21:30)</td>
295               <td>&nbsp; &nbsp;</td>
296               <td>&nbsp; &nbsp;</td>
297               <td>&nbsp; &nbsp;</td>
298               <td>&nbsp; &nbsp;</td>
299               <td>&nbsp; &nbsp;</td>
300               <td>&nbsp; &nbsp;</td>
301               <td>&nbsp; &nbsp;</td></tr>
302           </table>
303 
304 */
View Code

 

5、关于回调函数的使用

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

6、Demo演示

7、总结

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

  以上。

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

这篇关于HttpClient + Jsoup模拟登录教务处并获取课表的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/211913

相关文章

Security OAuth2 单点登录流程

单点登录(英语:Single sign-on,缩写为 SSO),又译为单一签入,一种对于许多相互关连,但是又是各自独立的软件系统,提供访问控制的属性。当拥有这项属性时,当用户登录时,就可以获取所有系统的访问权限,不用对每个单一系统都逐一登录。这项功能通常是以轻型目录访问协议(LDAP)来实现,在服务器上会将用户信息存储到LDAP数据库中。相同的,单一注销(single sign-off)就是指

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

usaco 1.2 Transformations(模拟)

我的做法就是一个一个情况枚举出来 注意计算公式: ( 变换后的矩阵记为C) 顺时针旋转90°:C[i] [j]=A[n-j-1] [i] (旋转180°和270° 可以多转几个九十度来推) 对称:C[i] [n-j-1]=A[i] [j] 代码有点长 。。。 /*ID: who jayLANG: C++TASK: transform*/#include<

【测试】输入正确用户名和密码,点击登录没有响应的可能性原因

目录 一、前端问题 1. 界面交互问题 2. 输入数据校验问题 二、网络问题 1. 网络连接中断 2. 代理设置问题 三、后端问题 1. 服务器故障 2. 数据库问题 3. 权限问题: 四、其他问题 1. 缓存问题 2. 第三方服务问题 3. 配置问题 一、前端问题 1. 界面交互问题 登录按钮的点击事件未正确绑定,导致点击后无法触发登录操作。 页面可能存在

hdu4431麻将模拟

给13张牌。问增加哪些牌可以胡牌。 胡牌有以下几种情况: 1、一个对子 + 4组 3个相同的牌或者顺子。 2、7个不同的对子。 3、13幺 贪心的思想: 对于某张牌>=3个,先减去3个相同,再组合顺子。 import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.IOExcepti

【每日一题】LeetCode 2181.合并零之间的节点(链表、模拟)

【每日一题】LeetCode 2181.合并零之间的节点(链表、模拟) 题目描述 给定一个链表,链表中的每个节点代表一个整数。链表中的整数由 0 分隔开,表示不同的区间。链表的开始和结束节点的值都为 0。任务是将每两个相邻的 0 之间的所有节点合并成一个节点,新节点的值为原区间内所有节点值的和。合并后,需要移除所有的 0,并返回修改后的链表头节点。 思路分析 初始化:创建一个虚拟头节点

Android Environment 获取的路径问题

1. 以获取 /System 路径为例 /*** Return root of the "system" partition holding the core Android OS.* Always present and mounted read-only.*/public static @NonNull File getRootDirectory() {return DIR_ANDR

每日一题|牛客竞赛|四舍五入|字符串+贪心+模拟

每日一题|四舍五入 四舍五入 心有猛虎,细嗅蔷薇。你好朋友,这里是锅巴的C\C++学习笔记,常言道,不积跬步无以至千里,希望有朝一日我们积累的滴水可以击穿顽石。 四舍五入 题目: 牛牛发明了一种新的四舍五入应用于整数,对个位四舍五入,规则如下 12345->12350 12399->12400 输入描述: 输入一个整数n(0<=n<=109 ) 输出描述: 输出一个整数

【算法专场】模拟(下)

目录 前言 38. 外观数列 算法分析 算法思路 算法代码 1419. 数青蛙 算法分析 算法思路 算法代码  2671. 频率跟踪器 算法分析 算法思路 算法代码 前言 在前面我们已经讲解了什么是模拟算法,这篇主要是讲解在leetcode上遇到的一些模拟题目~ 38. 外观数列 算法分析 这道题其实就是要将连续且相同的字符替换成字符重复的次数+

模拟实现vector中的常见接口

insert void insert(iterator pos, const T& x){if (_finish == _endofstorage){int n = pos - _start;size_t newcapacity = capacity() == 0 ? 2 : capacity() * 2;reserve(newcapacity);pos = _start + n;//防止迭代