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的代码了,如下:

 package com.example.upr.net;

 import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List; import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.cookie.Cookie;
import org.apache.http.impl.client.AbstractHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements; import com.example.upr.CompleteListener; import android.R.integer;
import android.os.AsyncTask;
import android.provider.ContactsContract.Contacts.Data;
import android.util.Log;
import android.widget.Toast; public class Login extends AsyncTask<Void, Void, String[][]>{ private String zjh;
private String mm;
private String webPage;
private String [][] kebiao = new String[15][8];
private CompleteListener listener;
public Login(String account, String password, CompleteListener listener) {
zjh = account;
mm = password; this.listener = listener;
}
@Override
protected String[][] doInBackground(Void... arg0) {
List<NameValuePair> list = new ArrayList<NameValuePair>();
list.add(new BasicNameValuePair("zjh", zjh));
list.add(new BasicNameValuePair("mm", mm));//表单信息
String encode = "gb2312";//编码格式,从F12工具中可以找到
HttpClient httpClient = new DefaultHttpClient();
List<Cookie> cookies;
try {
HttpEntity entity = new UrlEncodedFormEntity(list ,encode);//封装数据
HttpPost post = new HttpPost(com.example.upr.Constant.LOGIN_URL);//建立POST请求
post.setEntity(entity);
HttpResponse httpResponse = httpClient.execute(post);
String data, result;
if (httpResponse.getStatusLine().getStatusCode() == 200) {//登录成功
cookies = ((AbstractHttpClient) httpClient).getCookieStore().getCookies();//获取Cookie
HttpGet httpGet = new HttpGet("http://zhjw.dlut.edu.cn/xkAction.do?actionType=6");
httpGet.setHeader("Cookie", "JSESSIONID="+ cookies.get(0).getValue()+";"+
"NSC_kjbpxv-iuuq="+cookies.get(1).getValue());//注意分号
httpResponse = new DefaultHttpClient().execute(httpGet); StringBuffer sb = new StringBuffer();
entity = httpResponse.getEntity();
InputStream inputStream = entity.getContent();
BufferedReader br = new BufferedReader(new InputStreamReader(inputStream, encode));
while ((data = br.readLine()) != null) {
sb.append(data); //读取返回的网页
}
result = sb.toString();
webPage = result; } else {
return null;
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return null;
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
} Document document = Jsoup.parse(webPage);
if (document != null) {
Element element = document.getElementById("user");//通过id直接定位到数据
Elements trElements = element.select("tr");
//以下是提取课表信息,每个网站不同,一下代码要解析的html放在最下面了
for (int i = 0; i < trElements.size(); i++) {
Elements tdElements = trElements.get(i).select("td");
for (int j = 0; j < tdElements.size(); j++) {
String text = tdElements.get(j).text();
if (tdElements.size() == 1) {
continue;
} else if (tdElements.size()==9) {
if (j != 0) {
kebiao[i][j-1] = text;
}
}else {
kebiao[i][j] = text;
} }
}
return kebiao;
} else {
return null;
} }
@Override
protected void onPostExecute(String[][] result) {
super.onPostExecute(result);
listener.onConnectFinish(result);//执行回调函数,更新主UI
}
}
/*
<table cellpadding="0" width="100%" class="displayTag" cellspacing="0" border="1" id="user">
<tr>
<td colspan="2" class="sortable">&nbsp;</td>
<td width="13%" class="sortable">
<div align="center">星期一</div></td>
<td width="13%" class="sortable">
<div align="center">星期二</div></td>
<td width="13%" class="sortable">
<div align="center">星期三</div></td>
<td width="13%" class="sortable">
<div align="center">星期四</div></td>
<td width="13%" class="sortable">
<div align="center">星期五</div></td>
<td width="13%" class="sortable">
<div align="center">星期六</div></td>
<td width="13%" class="sortable">
<div align="center">星期日</div></td>
</tr>
<tr bgcolor="#FFFFFF">
<td width="3%" rowspan="4">&nbsp;
<p class="style4">上午</p></td>
<td width="11%">第1节(08:00-08:45)</td>
<td>&nbsp; 计算机网络A_01(西部校区综合教学2号楼B406)
<br></td>
<td>&nbsp; &nbsp;</td>
<td>&nbsp; &nbsp;</td>
<td>&nbsp; 编译原理_01(校部综合教学1号楼综151)
<br></td>
<td>&nbsp; 计算机组成原理_01(西部校区综合教学2号楼B103)
<br></td>
<td>&nbsp; &nbsp;</td>
<td>&nbsp; &nbsp;</td></tr>
<tr bgcolor="#FFFFFF">
<td width="11%">第2节(08:50-09:35)</td>
<td>&nbsp; 计算机网络A_01(西部校区综合教学2号楼B406)
<br></td>
<td>&nbsp; &nbsp;</td>
<td>&nbsp; &nbsp;</td>
<td>&nbsp; 编译原理_01(校部综合教学1号楼综151)
<br></td>
<td>&nbsp; 计算机组成原理_01(西部校区综合教学2号楼B103)
<br></td>
<td>&nbsp; &nbsp;</td>
<td>&nbsp; &nbsp;</td></tr>
<tr bgcolor="#FFFFFF">
<td width="11%">第3节(10:05-10:50)</td>
<td>&nbsp; &nbsp;</td>
<td>&nbsp; 面向对象程序设计_01(西部校区综合教学2号楼A301)
<br></td>
<td>&nbsp; &nbsp;</td>
<td>&nbsp; 人工智能_01(西部校区综合教学2号楼A101)
<br></td>
<td>&nbsp; &nbsp;</td>
<td>&nbsp; &nbsp;</td>
<td>&nbsp; &nbsp;</td></tr>
<tr bgcolor="#FFFFFF">
<td width="11%">第4节(10:55-11:40)</td>
<td>&nbsp; &nbsp;</td>
<td>&nbsp; 面向对象程序设计_01(西部校区综合教学2号楼A301)
<br></td>
<td>&nbsp; &nbsp;</td>
<td>&nbsp; 人工智能_01(西部校区综合教学2号楼A101)
<br></td>
<td>&nbsp; &nbsp;</td>
<td>&nbsp; &nbsp;</td>
<td>&nbsp; &nbsp;</td>
<tr bgcolor="#FFFFFF">
<td colspan="9">&nbsp;
<p align="center" class="td2 style5">
<strong>午 休</strong></p>
</td>
</tr>
</tr>
<tr bgcolor="#FFFFFF">
<td width="3%" rowspan="4">&nbsp;
<p class="style4">下午</p></td>
<td width="11%">第5节(13:30-14:15)</td>
<td>&nbsp; 编译原理_01(校部综合教学1号楼综151)
<br></td>
<td>&nbsp; 计算机组成原理_01(西部校区综合教学2号楼B103)
<br></td>
<td>&nbsp; &nbsp;</td>
<td>&nbsp; 计算机网络A_01(西部校区综合教学2号楼B406)
<br></td>
<td>&nbsp; &nbsp;</td>
<td>&nbsp; &nbsp;</td>
<td>&nbsp; &nbsp;</td></tr>
<tr bgcolor="#FFFFFF">
<td width="11%">第6节(14:20-15:05)</td>
<td>&nbsp; 编译原理_01(校部综合教学1号楼综151)
<br></td>
<td>&nbsp; 计算机组成原理_01(西部校区综合教学2号楼B103)
<br></td>
<td>&nbsp; &nbsp;</td>
<td>&nbsp; 计算机网络A_01(西部校区综合教学2号楼B406)
<br></td>
<td>&nbsp; &nbsp;</td>
<td>&nbsp; &nbsp;</td>
<td>&nbsp; &nbsp;</td></tr>
<tr bgcolor="#FFFFFF">
<td width="11%">第7节(15:35-16:20)</td>
<td>&nbsp; 人工智能_01(西部校区综合教学2号楼A101)
<br></td>
<td>&nbsp; &nbsp;</td>
<td>&nbsp; &nbsp;</td>
<td>&nbsp; &nbsp;</td>
<td>&nbsp; 面向对象程序设计_01(西部校区综合教学2号楼A301)
<br></td>
<td>&nbsp; &nbsp;</td>
<td>&nbsp; &nbsp;</td></tr>
<tr bgcolor="#FFFFFF">
<td width="11%">第8节(16:25-17:10)</td>
<td>&nbsp; 人工智能_01(西部校区综合教学2号楼A101)
<br></td>
<td>&nbsp; &nbsp;</td>
<td>&nbsp; &nbsp;</td>
<td>&nbsp; &nbsp;</td>
<td>&nbsp; 面向对象程序设计_01(西部校区综合教学2号楼A301)
<br></td>
<td>&nbsp; &nbsp;</td>
<td>&nbsp; &nbsp;</td>
<tr bgcolor="#FFFFFF">
<td colspan="9">&nbsp;
<p align="center" class="td2 style5">
<strong>晚 饭</strong></p>
</td>
</tr>
</tr>
<tr bgcolor="#FFFFFF">
<td width="3%" rowspan="4">&nbsp;
<p class="style4">晚上</p></td>
<td width="11%">第9节(18:00-18:45)</td>
<td>&nbsp; 社会学*_886(校部综合教学1号楼综152)
<br></td>
<td>&nbsp; 人类文明史*_887(校部材料馆材101)
<br></td>
<td>&nbsp; &nbsp;</td>
<td>&nbsp; &nbsp;</td>
<td>&nbsp; &nbsp;</td>
<td>&nbsp; &nbsp;</td>
<td>&nbsp; &nbsp;</td></tr>
<tr bgcolor="#FFFFFF">
<td width="11%">第10节(18:55-19:40)</td>
<td>&nbsp; 社会学*_886(校部综合教学1号楼综152)
<br></td>
<td>&nbsp; 人类文明史*_887(校部材料馆材101)
<br></td>
<td>&nbsp; &nbsp;</td>
<td>&nbsp; &nbsp;</td>
<td>&nbsp; &nbsp;</td>
<td>&nbsp; &nbsp;</td>
<td>&nbsp; &nbsp;</td></tr>
<tr bgcolor="#FFFFFF">
<td width="11%">第11节(19:50-20:35)</td>
<td>&nbsp; 社会学*_886(校部综合教学1号楼综152)
<br></td>
<td>&nbsp; 人类文明史*_887(校部材料馆材101)
<br></td>
<td>&nbsp; &nbsp;</td>
<td>&nbsp; &nbsp;</td>
<td>&nbsp; &nbsp;</td>
<td>&nbsp; &nbsp;</td>
<td>&nbsp; &nbsp;</td></tr>
<tr bgcolor="#FFFFFF">
<td width="11%">第12节(20:45-21:30)</td>
<td>&nbsp; &nbsp;</td>
<td>&nbsp; &nbsp;</td>
<td>&nbsp; &nbsp;</td>
<td>&nbsp; &nbsp;</td>
<td>&nbsp; &nbsp;</td>
<td>&nbsp; &nbsp;</td>
<td>&nbsp; &nbsp;</td></tr>
</table> */

5、关于回调函数的使用

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

6、Demo演示

7、总结

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

  以上。

HttpClient + Jsoup模拟登录教务处并获取课表的更多相关文章

  1. HttpClient+Jsoup模拟登陆贺州学院教务系统,获取学生个人信息

    前言 注:可能学校的教务系统已经做了升级,当前的程序不知道还能不能成功获取信息,加上已经毕业,我的账户已经被注销,试不了,在这里做下思路跟过程的记录. 在我的毕业设计中”基于SSM框架贺州学院校园二手 ...

  2. 利用Jsoup模拟跳过登录爬虫获取数据

    今天在学习爬虫的时候想着学习一下利用jsoup模拟登录.下面分为有验证码和无验证码的情况进行讨论. ---------------------------无验证码的情况---------------- ...

  3. 基于HttpClient的新版正方教务系统模拟登录及信息获取API

    简介 通过HttpClient获取网页数据源,通过Jsoup解析数据.先模拟登录,再获取信息.模拟浏览器正常操作,封装请求头信息获取SESSIONID.模拟登录成功后切勿断开会话,依赖登录请求得到的C ...

  4. node.js模拟学校教务处登录

    临近毕业,在做毕设,我的毕设中有一个功能是模拟我学校的教务处登录以获得cookie,本来以为是挺简单的一个功能,但却花了我两天的时间.(我学校教务处用的是湖南强智科技开发的) 在网上搜了大量的模拟登录 ...

  5. Python 爬虫实战5 模拟登录淘宝并获取所有订单

    经过多次尝试,模拟登录淘宝终于成功了,实在是不容易,淘宝的登录加密和验证太复杂了,煞费苦心,在此写出来和大家一起分享,希望大家支持. 本篇内容 python模拟登录淘宝网页 获取登录用户的所有订单详情 ...

  6. C#程序模拟登录批量获取各种邮件内容信息

    一般来说,如果现实中你有这样一种需求“假如你是褥羊毛的羊毛党,你某日发现了一个app有一个活动,通过邮箱注册账号激活可以领5元红包,而恰恰你手上又有一批邮箱可用,那么批量获取邮箱中的激活链接去激活则是 ...

  7. Android利用HttpURLConnection实现模拟登录

    最近在做一个APP,需要模拟登录教务处,之前曾经用HttpClient做过,点这里,但是发现最新的Android SDK已经不支持Httpclient了,所以只好在琢磨一下HttpURLConnect ...

  8. Java通过httpclient获取cookie模拟登录

    package Step1; import org.apache.commons.httpclient.Cookie; import org.apache.commons.httpclient.Htt ...

  9. 记一次HTTPClient模拟登录获取Cookie的开发历程

    记一次HTTPClient模拟登录获取Cookie的开发历程 环境: ​ springboot : 2.7 ​ jdk: 1.8 ​ httpClient : 4.5.13 设计方案 ​ 通过新建一个 ...

随机推荐

  1. QT 数据库编程三

    //mainwindow.cpp #include "mainwindow.h" #include "logindlg.h" #include "sc ...

  2. addShutdownHook的用法

    addShutdownHook作为一个正常关闭Java程序的途径,其实是非常有用的. 有JDK文档可知,当程序正常退出,或者为响应用户中断而终止虚拟机的时候,就会调用里面的线程,来作最后的退出处理. ...

  3. GET请求参数为中文时乱码分析

    问题描述 近期做任务时,跟后端联调时遇到一个问题,前端发送get请求,当参数值有中文时,请求失败,请求参数变为乱码.(ps:一般当参数有中文时,很少使用get请求,而是使用post请求来传输数据,请求 ...

  4. Hashtable Dictionary List 谁效率更高

    一 前言 很少接触HashTable晚上回来简单看了看,然后做一些增加和移除的操作,就想和List 与 Dictionary比较下存数据与取数据的差距,然后便有了如下的一此测试, 当然我测的方法可能不 ...

  5. Asp.Net Core-几行代码解决Razor中的嵌套if语句

    MVC开发中,经常会遇到在razor中插入简单的逻辑判断. @if (clientManager.IsAdmin) { if (!Model.Topic.Top) { <a asp-action ...

  6. 移动端前端UI库—Frozen UI、WeUI、SUI Mobile

    [MUI]http://www.dcloud.io/ [Clouda]http://clouda.baidu.com/blend2是百度历时两年共同研发的开源App技术框架,基于Node.js,简单易 ...

  7. XML是什么东西

    记住,XML就是为数据传输而设计的一种标记语言,也是特么的一种标记语言,在这点上,和html是有点类似的,你看<xml>和<html>看上去难道不是很像嘛,而html是为数据显 ...

  8. Python基础-函数篇

    本节内容 1. 函数基本语法及特性 2. 参数与局部变量 3. 返回值 嵌套函数 4.递归 5.匿名函数 6.函数式编程介绍 7.高阶函数 8.内置函数  函数与函数式编程 1.面向对象: 华山派-- ...

  9. Day Three(Beta)

    站立式会议 站立式会议内容总结 331 今天:列表关于div控制长度选择控制字段长度而非cssCtrl;editor学习使用 遇到的问题:无 明天:复习,没什么时间花在代码上,可以构思下闹钟的过程 4 ...

  10. python 2.7 和3.0input区别

    name = raw_input('请输入用户名:')#python2.7的用法 name = input('请输入用户名:')#python3.0的用法 print(name)