大家好,我是M1ko。在互联网时代的今天,如果一个App不接入互联网,那么这个App一定不会有长时间的生命周期,因此Android网络编程是每一个Android开发者必备的技能,博主是在校大学生,自学Android一年半多,正好通过一个模拟登录校园网软件,来给大家演示如何在网页上抓取我们想要的数据,以及将数据Post给服务器。如果有什么错误或改进欢迎大家指正=-= ,如果想交流博主qq 136057505

好的废话不多说看一下我们的重点

  • Httpwatch等软件抓取Post请求
  • 如何获取验证码
  • 使用Jsoup解析数据

    Ok首先上项目Github网址:https://github.com/MikoGodZd/LoginNwuWeb1.git
    下面是软件的截图大家心里能有项目的大体框架

一、Http基础

有Http基础的朋友都知道,我们是通过Get 与Post请求与服务器进行交互的,Get顾名思义就是获取信息,Post就是想服务器发请求,但是Post也可以用来获取信息并且比Get有很多优势,我们这里就是使用的Post。Java中有很多方式与服务器进行连接,常见的有HttpUrlCollection,HttpClient。两者的优缺点:

HttpUrlCollection优点:
- 轻量,拓展性强
- 节省资源
缺点:
- 代码量大复杂

HttpClient优点:
- 便捷,代码简单
缺点:
-拓展性不足,耗费资源多

实际上在Android6.0中Google已经删除了HttpClient的API官方理由是耗电量大,但是HttpCollection的代码量实在是大,因此我们还是使用了HttpClient,只需在build.gradle中添加以下语句
android {
useLibrary 'org.apache.http.legacy'
}
即可。

二、服务器地址的获取 ##

我们要向服务器Post数据要知道Post的地址是谁,这就要用我们的抓包软件了,博主使用的是HttpWatch与火狐的FireBug,两个软件的功能相互补充,两个软件基本的使用方法大家自行Google(百度,嘿嘿嘿=-=)
1.验证码的地址
ok首先打开我们的校园网登录网页:
http://jwxt.nwu.edu.cn/%28dlxrmg55j21wlaqv2z5rcdyi%29/Default2.aspx
我们点击IE 中HttpWatch Record按钮,然后刷新这个网站我们可以看到如下的界面

我们能够看到很多Get请求这些Get请求就能够获取打开的界面的各个元素,右键G右方的网址,选择Open in the new Tab就可以看到各个元素,细心(累死=-=)的查找之后我们发现验证码的网址是
http://jwxt.nwu.edu.cn/%28dlxrmg55j21wlaqv2z5rcdyi%29/CheckCode.aspx 打开后如下图显示

2.登陆post地址
获得验证码的地址之后,我们还要获得登陆服务器的地址,还是使用HttpWatch,我们输入进去账号密码以及验证码之后,单击登录开始抓取
打开下面的POST DATA就可以看到我们发送的数据以及他们的类别
__VIEWSTATE
Button1
hidPdrs
hidsc
lbLanguag
RadioButtonLi
TextBox2 密码
txtSecretCode 验证码
txtUserName 用户名 这里不给用户名,有需要的QQ 加我136057505=-=
这些值很关键,我们在这里面可以找到对应的值,如果没有值那就是空,好的这些我们下面会详细讲,我们还没有获得Post地址,右键Post这一行Copy即可,ok这样我们发送Post请求的地址就到手了。
http://jwxt.nwu.edu.cn/%28dlxrmg55j21wlaqv2z5rcdyi%29/Default2.aspx

三、登陆

1.验证码图片的获取
我们有了各种地址,下面就要登陆了,但是我们知道了账号和密码(嘿嘿嘿,就不告诉你们=-=),我们还要知道验证码,怎么获得图片呢?上文中我们已经知道了验证码的地址了,我们可以Get请求,但之前也说过一般使用Post请求来进行,于是我们上代码

  HttpPost httPost = new HttpPost(VERIFATIONURL);HttpClient client = new DefaultHttpClient();try {HttpResponse httpResponse = client.execute(httPost);byte[] bytes = new byte[1024];bytes = EntityUtils.toByteArray(httpResponse.getEntity());bmVerifation = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);} catch (IOException e) {e.printStackTrace();}

HttpClient的详细用法大家自行Google这里不详细展开
VERIFATIONURL就是上文中的验证码地址,首先创建post请求,再创建一个Httpclient ,然后是HttpResponse即响应,我们获取的服务器的返回值就在通过他获取,我们创建一个byte数组,首先将响应中获得的数据转化为byte数组,然后通过 BitmapFactory.decodeByteArray(bytes, 0, bytes.length);方法将byte数组编译为bitmap,这时候我们就获得了验证码的Bitmap了,我们能直接ImageView.SetBitmap么?当然不能,首先第一点我们在网页上获取图片是一个耗时操作,所以我们不能在主线程中进行,第二点只有在主线程中才能更新UI因此,我们使用Thread+Handler解决方法,上代码:

private void DoGetVerifation() {new Thread(new Runnable() {@Overridepublic void run() {HttpPost httPost = new HttpPost(VERIFATIONURL);HttpClient client = new DefaultHttpClient();try {HttpResponse httpResponse = client.execute(httPost);byte[] bytes = new byte[1024];bytes = EntityUtils.toByteArray(httpResponse.getEntity());bmVerifation = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);} catch (IOException e) {e.printStackTrace();}Message msg = new Message();msg.arg1 = 10;handler.sendMessage(msg);}}).start();}

主线程中接收到msg之后ivVerifation.setImageBitmap(bmVerifation);这样我们就得到了验证码的图片并且在主界面上显示出来了

2.发送Post请求登录

我们目前知道了用户名,密码,验证码,下一步就是要登录了,登陆同样是个耗时操作,当然也要开启一个新的线程,这没什么好说的了,我们同样是发送Post请求,上代码:

private void DoLogin(final String user, final String password, final String verifation) {new Thread(new Runnable() {@Overridepublic void run() {DefaultHttpClient defaultclient = new DefaultHttpClient();HttpPost httpPost = new HttpPost(LOGINURL);HttpResponse httpResponse;//设置post参数List<NameValuePair> params = new ArrayList<NameValuePair>();params.add(new BasicNameValuePair("__VIEWSTATE", "dDwyODE2NTM0OTg7Oz6ZmvWn7xzjizifHN9MgLoDNTRtjQ=="));params.add(new BasicNameValuePair("Button1", ""));params.add(new BasicNameValuePair("hidPdrs", ""));params.add(new BasicNameValuePair("hidsc", ""));params.add(new BasicNameValuePair("lbLanguage", ""));params.add(new BasicNameValuePair("RadioButtonList1", "%D1%A7%C9%FA"));params.add(new BasicNameValuePair("TextBox2", password));params.add(new BasicNameValuePair("txtSecretCode", verifation));params.add(new BasicNameValuePair("txtUserName", user));//获得个人主界面的HTMLtry {httpPost.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));httpResponse = defaultclient.execute(httpPost);Log.i("xyz", String.valueOf(httpResponse.getStatusLine().getStatusCode()));if (httpResponse.getStatusLine().getStatusCode() == 200) {StringBuffer sb = new StringBuffer();HttpEntity entity = httpResponse.getEntity();MAINBODYHTML = EntityUtils.toString(entity);IsLoginSuccessful(MAINBODYHTML);}} catch (UnsupportedEncodingException e) {e.printStackTrace();} catch (ClientProtocolException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}}).start();}

首先是创建post,client response,与前面无异,我们获取数据的Post请求,比如说获取验证码请求是不需要参数的,但是我们登录需要发送给服务器 用户名 密码 验证码,于是我们为Post请求设置参数

 //设置post参数List<NameValuePair> params = new ArrayList<NameValuePair>();params.add(new BasicNameValuePair("__VIEWSTATE", "dDwyODE2NTM0OTg7Oz6ZmvWn7xzjizifHN9MgLoDNTRtjQ=="));params.add(new BasicNameValuePair("Button1", ""));params.add(new BasicNameValuePair("hidPdrs", ""));params.add(new BasicNameValuePair("hidsc", ""));params.add(new BasicNameValuePair("lbLanguage", ""));params.add(new BasicNameValuePair("RadioButtonList1", "%D1%A7%C9%FA"));params.add(new BasicNameValuePair("TextBox2", password));params.add(new BasicNameValuePair("txtSecretCode", verifation));params.add(new BasicNameValuePair("txtUserName", user));//获得个人主界面的HTMLtry {httpPost.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));httpResponse = defaultclient.execute(httpPost);Log.i("xyz", String.valueOf(httpResponse.getStatusLine().getStatusCode()));if (httpResponse.getStatusLine().getStatusCode() == 200) {StringBuffer sb = new StringBuffer();HttpEntity entity = httpResponse.getEntity();MAINBODYHTML = EntityUtils.toString(entity);IsLoginSuccessful(MAINBODYHTML);}} catch (UnsupportedEncodingException e) {e.printStackTrace();} catch (ClientProtocolException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}

这些参数就是我们之前使用HttpWatch获取的Post data 只有类型没有值的参数我们设置为“”空,使用httpPost.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));方法将我们设置的param 参数集合给httppost,下面和之前一样,也是通过Response获取响应值,只不过这里返回的不是图片而是赤果果的String=-=,IsLoginSuccessful这个函数是用来判断我们是否登录成功,这就要用到我们下面要说的数据解析了。

四、数据解析

1.返回的响应?
我们登陆后会得到服务器给我们的响应,我们在火狐的Firebug(HttpWatch也可以个人感觉看响应值Firebug比较方便)上机型一次成功的登陆,看一下他究竟会给我们返回什么
如图我们可以知道实际上响应值就是我们的网页的HTML,如果登陆成功实际上就是返回个人首页

那么如果失败呢?我们模拟一次验证码错误如下图,可见同样返回一个HTML

我们注意这一行

<script language='javascript' defer>alert('验证码不正确!!');document.getElementById('TextBox2').focus();
</script>

这实际上是弹出一个窗口,提示我们验证码错误,下面我们就会利用里面不同的提示来判断我们登陆的状态

2.使用Jsoup进行数据解析
我们创建之前提过的IsLoginSuccessful函数

   private void IsLoginSuccessful(String loginresult) {Document doc = Jsoup.parse(loginresult);Elements alert = doc.select("script[language]");Elements success = doc.select("a[href]");Message msg = new Message();//先判断是否登录成功,若成功直接退出for (Element link : success) {//获取所要查询的URL,这里对应地址按钮的名字叫成绩查询if (link.text().equals("等级考试查询")) {Log.i("xyz", "登录成功");msg.arg1 = 6;handler.sendMessage(msg);return;}}for (Element link : alert) {//刷新验证码DoGetVerifation();//获取错误信息if (link.data().contains("验证码不正确")) {Log.i("xyz", "验证码错误");msg.arg1 = 0;handler.sendMessage(msg);} else if (link.data().contains("用户名不能为空")) {Log.i("xyz", "用户名不能为空");msg.arg1 = 1;handler.sendMessage(msg);} else if (link.data().contains("密码错误")) {Log.i("xyz", "密码或用户名错误");msg.arg1 = 2;handler.sendMessage(msg);} else if (link.data().contains("密码不能为空")) {Log.i("xyz", "密码不能为空");msg.arg1 = 3;handler.sendMessage(msg);......}}

我使用的是一个开源的库Jsoup进行解析当然还有很多方法,大家自行Google(百度=-=咋老躺枪)
http://www.open-open.com/jsoup/ Jsoup的中文API指南大家可以看一下
首先我们判断登陆成功,我们在登陆成功的HTML中找到了如下语句

<a href="xsdjkscx.aspx?xh=2014117170&xm=邹德宏&gnmkdm=N121606" target='zhuti' onclick="GetMc('等级考试查询');">
等级考试查询</a>

我们通过 Elements success = doc.select(“a[href]”);获取到a href”开头的数据 然后我们循环判断是否存在等级考试查询这一项,如果存在,那肯定返回的响应就是我们的个人首页了,也就是说登陆成功,我们使用Thread+Handler在主线程中Toast提醒用户
然后我们通过 Elements alert = doc.select(“script[language]”);获取到script 开头的语句,同样循环判断,这里要注意的是,与a href不同的是,我们要用的是link.data(),前面用的是link.text();
JsoupAPI 这样写的

  • text()获取文本内容text(String value) 设置文本内容
  • data()获取数据内容(例如:script和style标签)
    ok我们通过不同的模拟操作抓取各种错误,这里不详写

五、获取个人信息

我们登录到了个人首页,我们想进一步获取自己的信息比如说四六级成绩,怎么办呢?同样还是抓取请求

跟获取验证码网址的方法一样,我们得到了成绩表的网址
http://jwxt.nwu.edu.cn/(dlxrmg55j21wlaqv2z5rcdyi)/xsdjkscx.aspx?xh=2014117170&xm=邹德宏&gnmkdm=N121606
前面http://jwxt.nwu.edu.cn/(dlxrmg55j21wlaqv2z5rcdyi)/是我们访问的host是不变的,我们要做的就是获取xsdjkscx.aspx?xh=2014117170&xm=邹德宏&gnmkdm=N121606,这个问题困扰了很长时间,后来猛然发现这万至竟然在前面说的deng’lu’cheng’登陆成功后返回的HTML中,所以还是使用Jsoup进行分析

 Document doc = Jsoup.parse(MAINBODYHTML);Elements links = doc.select("a[href]");StringBuffer sb = new StringBuffer();for (Element link : links) {//获取所要查询的URL,这里对应地址按钮的名字叫成绩查询if (link.text().equals("等级考试查询")) {sb.append(link.attr("href"));}}GETSCOREURL = sb.toString();

GETSCOREURL就是我们要的后半个地址,然后我们加上前半个,进行Post请求抓取即可
这里返回的是一个Html的表格

<table class="datelist" cellspacing="0" cellpadding="3" border="0" id="DataGrid1" width="100%"
><tr class="datelisthead"><td>学年</td><td>学期</td><td>等级考试名称</td><td>准考证号</td><td>考试日期</td><td>成绩</td><td>听力成绩</td><td>阅读成绩</td
><td>写作成绩</td><td>综合成绩</td></tr><tr><td>2014-2015</td><td>2</td><td>CET4</td><td>610041151112625</td><td>201506</td><td>483</td><td>167
</td><td>173</td><td>143</td><td>0</td></tr><tr class="alt"><td>2015-2016</td><td>1</td><td>CET6</td><td>610041152209503</td><td>201512</td><td>376</td><td>126
</td><td>143</td><td>107</td><td>0</td></tr>
</table>

同样使用Jsoup

 private void parse(String parse) {Document doc = Jsoup.parse(parse);Elements trs = doc.select("table").select("tr");for (int i = 0; i < trs.size(); i++) {Elements tds = trs.get(i).select("td");for (int j = 0; j < tds.size(); j++) {String text = tds.get(j).text();score[i][j] = text;Log.i("xyz", score[i][j]);}}}

解析完我们就得到成绩的数组了

六、总结

博主大二党自学Android开发1年半了,现在终于有入门的感觉了,这篇教程对新手来说坑能会有些难,但是一定要沉得住气,博主刚下载HttpWatch那一会都懵逼了,啥都不懂,慢慢摸索之后终于有了头绪,好了就这么些,邮箱交流的朋友加我QQ 136057505=-=

Android登录客户端,验证码的获取,网页数据抓取与解析,HttpWatch基本使用相关推荐

  1. 如何用python抓取文献_浅谈Python爬虫技术的网页数据抓取与分析

    浅谈 Python 爬虫技术的网页数据抓取与分析 吴永聪 [期刊名称] <计算机时代> [年 ( 卷 ), 期] 2019(000)008 [摘要] 近年来 , 随着互联网的发展 , 如何 ...

  2. 李沐【实用机器学习】1.3网页数据抓取

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 一.数据抓取工具 二.实例解析 总结 前言 网页数据抓取目标:在一个网站里面感兴趣的数据抓取出来 数据特点:噪点较多, ...

  3. 网页数据抓取之当当网

    所谓"网页数据抓取",也称为网页数据采集,Web数据采集等等,就是从我们平时通过浏览器查看的web网页上来提取需要的数据信息,然后以结构化的方式存储到CSV.JSON.XML.AC ...

  4. 网页数据抓取,关键在于抓取的准确性和应对海量数据时的快速反应

    无论是互联网科技.大数据.还是云计算,关键都在于技术优势,技术的成本和门槛都很高,不是两三个人零成本就可以打造一个产品. 我们以网页数据抓取来说,一门基于web结构或基于浏览器可视化的数据获取技术,关 ...

  5. 网页数据抓取-网页实时数据抓取软件

    网页数据抓取,随着社会的发展,互联网的普及,不管是企业还是个人都意识到数据的重要性.今天给大家分享一款免费的网页数据抓取软件.只要点点鼠标就能轻松采集你想要的内容不管是导出还是自动发布都支持!详细参考 ...

  6. 1.3 网页数据抓取

    1.3 网页数据抓取 李沐 B站:https://space.bilibili.com/1567748478/channel/collectiondetail?sid=28144 课程主页:https ...

  7. python模拟登录淘宝直通车_Python实现的淘宝直通车数据抓取(2)

    再看我们要抓取的数据,网页是这样的: 这里是我们要抓取的数据: 打开chrome的调试工具发现数据是通过一个Ajax请求来获取的: 这样的话,获取数据就太简单了,因为完全不需要去解析html页面,只需 ...

  8. vba抓取网页数据到excel_R语言网页数据抓取XML数据包

    有些网络上的数据无法复制粘贴,一个一个录入有点费时费力,此时用这种数据抓取方法,短短几句,简单实用.XML是一种可扩展标记语言,它被设计用来传输和存储数据.XML是各种应用程序之间进行数据传输的最常用 ...

  9. Jmeter压力测试 Web网页数据抓取-【教学篇】

    Jmeter快速使用 特此郑重声明!该文章是原创作品,小编编写实属不易 ,转载小伙伴请注明出处!谢谢 概述 Apache JMeter Apache组织开发的压力测试工具.目前通过HTTP和FTP服务 ...

最新文章

  1. java操作mongodb基础(查询 排序 输出list)
  2. Android开发之动态库调用
  3. 定义css设备类型-Media Queries图表简介及使用方法
  4. Linux学习之系统编程篇:利用 shm 进行进程间通信
  5. SQLite 入门教程(四)增删改查,有讲究
  6. Asp:Response对象
  7. 剑指offer(21)栈的压入、探出序列
  8. python runtimeeeror_Python3基础 raise 产生RuntimeError 异常
  9. 【非常基础实践】 微信小程序 - 腾讯云 - PHP - DEMO - 002 - 云环境搭建和开通指引- 实践
  10. byte转换字符串(string)+字符串转换byte
  11. 爬虫选用PPTP协议代理ip的必要性
  12. matlab隐函数参数拟合,matlab拟合隐函数参数(1stOpt拟合7参数请求代跑)
  13. 项目合同管理 考纲与考试要点
  14. python mp4提取音频_Python从视频文件中提取wav
  15. 非常火的斗图表情包小程序源码
  16. ESP-MESH 无线组网,让智能家居通信组网更方便 | ESP32轻松学(Arduino版)
  17. mongodb-报错FailedToParse: Password must be URL Encoded for mongodb:// URL:
  18. 这三年,一路走来,劈荆斩棘 – Vol 1
  19. 【01】什么是 APP?移动 APP 有几种类型?
  20. 恢复文件默认打开方式

热门文章

  1. 曝光的原理 自动曝光
  2. Java进阶(四)多态
  3. IDEA/GoLand 添加自定义特殊注释【注释高亮】
  4. Object.assign与vue $set
  5. js实现粒子特效,particles.js的使用
  6. [转]SSD:Single Shot Detector详解
  7. 喷墨打印机的使用 hp LaserJet 1010 HB 打印顺序
  8. xctf攻防世界 MISC高手进阶区 Ditf
  9. 基于Javaweb实现的人脸识别考勤系统
  10. 如何使用Redis缓存 ?