APP下载

基于HttpClient的Android客户端的设计与实现

2014-04-29王超闾陈莉吴迪项英杰

计算机时代 2014年3期

王超 闾陈莉 吴迪 项英杰

摘 要: 移动设备的普及和移动互联网的高速发展让人们开始依赖通过移动设备获取信息,但普通页面在移动端的体验很难满足用户的需求。为此研究了HttpClient和Jsoup等技术,分析了一般网站的登录原理,成功实现了对一般网站的模拟登录和页面信息的提取,在此基础上实现的系统可以在目标网站中获取用户所需的信息,并将这些信息整合应用到Android平台,从而设计出用户体验更佳的网站Android客户端。

关键词: HttpClient; Jsoup; Android; 模拟登录

中图分类号:TP311 文献标志码:A 文章编号:1006-8228(2014)03-30-03

0 引言

客户端(Client)或称为用户端,是指与服务器相对应,为客户提供本地服务的程序。而Android系统上90%的客户端软件具有一个共性:为了改善网页在Android系统上体验不佳而生。这类软件最突出的特点是:先有网站再有客户端。由于网络技术发展的多样性,手机浏览器往往无法跟随它的步伐,为改善用户体验,网站客户端软件应运而生。

由于一般网站不提供服务端的开放平台,我们无法调用所提供的API接口来开发,所以需要对页面信息进行处理分析。在对网页信息进行处理分析时,不可能采用浏览器人工阅览的方法,因此需要自己编写分析处理程序,提取出有用的信息,为进一步分析做准备。由于原始HTML页面的数据格式并不适合进行处理[1],本研究将结合HttpClient与Jsoup对HTML页面进行抓取解析。

1 开发工具与环境的介绍

1.1 HttpClient

网页抓取,就是把URL地址中指定的网络资源从网络流中读取出来,保存到本地。类似于使用程序模拟IE浏览器的功能,把URL作为HTTP请求的内容发送到服务器端,然后读取服务器端的相应资源[2]。虽然java.net包中已经提供了访问HTTP协议的基本功能,但是对于大部分应用程序来说还不够丰富和灵活。

HttpClient[3]是Apache Jakarta Common下的子项目,用来提供高效的、最新的、功能丰富的、支持HTTP协议的客户端编程工具包,并且支持HTTP协议最新的版本和建议。HttpClient能够处理HTTP连接中的各种问题,使用十分方便,只需导入HttpClient.jar包,就可以模拟IE浏览器来获取网页内容。

1.2 Jsoup

Jsoup分析网页结构和内容的功能远远强大于HtmlParser,无论是获取整个页面的文本,还是分析特定内容的网页结构,都十分方便。Jsoup数据获取有两大方法:①通过分析dom模型的网页标签和元素;②select元素选择器,类似Jquery方式。

1.3 Android

Android是一种基于Linux的自由及开放源代码的操作系统,主要适用于移动设备,如智能手机和平板电脑,由Google公司和开放手机联盟领导及开发。2011年第一季度,Android在全球的市场份额首次超过塞班系统,跃居全球第一。2012年11月的数据显示,Android占据全球智能手机操作系统市场76%的份额,中国市场占有率为90%。在2013年09月24日Android操作系统迎来5岁生日时,全球采用这款系统现有设备数量已经达到10亿台。

2 网站客户端开发的设计

2.1 获取数据的原理

图1是一个简单的示意图,告诉我们,数据是由网页从数据库中取出,要为这个系统做客户端,就应该按照该数据获取的原理去改造它,如图2所示。

[网页] [数据]

图1 网页从数据库中提取数据

[安卓客户端][网页] [数据]

图2 客户端间接访问数据库

通过这样间接的方法来访问数据库,只要网页能看到的内容,我们的客户端都能获取到,而UI是由用户自行制作,可以使用户体验上一个台阶。

2.2 HttpClient模拟登录原理

现如今不论是网站还是论坛,又或是一般的信息管理系统,登录功能都是必不可少的。因此我们若想要访问所需要的网站并从中获取数据,登录是无法跳过的一个环节[4]。

因为HTTP协议是无状态的,也就是连接的有效期只限于当前请求,请求内容结束后连接就关闭了。在这种情况下为了保存用户的登录信息必须使用Cookie机制[5]。以JSP/Servlet为例,当浏览器请求一个JSP或者是Servlet页面时,应用服务器会返回一个参数,名为jsessionid(因不同应用服务器而异),其值是一个较长的惟一字符串的Cookie,这个字符串也就是当前访问该站点的会话标识。浏览器每在访问该站点的其他页面时都要带上jsessionid这样的Cookie信息,应用服务器根据这个会话标识来获取对应的会话信息。

对于需要用户登录的网站,一般在用户登录成功后会将用户资料保存在服务器的会话中,当访问其他的页面时,应用服务器根据浏览器送上的Cookie读取当前请求对应的会话标识以获得对应的会话信息,然后就可以判断用户资料是否存在于会话信息中,如果存在则允许访问页面,否则跳转到登录页面中要求用户输入帐号和口令进行登录。这就是一般使用JSP开发的网站在处理用户登录时比较通用的方法。

对于HTTP的客户端而言,如果要访问一个受保护的页面,就必须模拟浏览器所做的工作,首先是请求登录页面,读取Cookie值;其次是请求登录页面并加入登录页所需的每个参数;最后是请求最终所需的页面。当然,除第一次请求之外,其他的请求都需要附带上Cookie信息以便服务器能判断当前请求是否已经通过验证。

在本研究中,通过HttpClient,可以方便地模拟出登录的http请求,并获取已经通过验证的Cookie,之后再通过该Cookie来进行所需页面的http请求,最终获取其数据。虽然HttpClient自身具有自动调去Cookie的机制,但仍建议能够自行调用代码传送Cookie。

3 网站客户端的实现

本次模拟登录和页面信息获取是在Java项目中完成的,由于Java项目可以完美移植到Android项目中,方便被调试,而且模拟Http请求这一过程并没有用到任何Android功能。运用HttpClient和 Jsoup技术的版本是HttpClient 3.x和Jsoup 1.6。

3.1 模拟登录实现

/*对HttpClient 的初始化*/

private HttpClient client;

client=new HttpClient();

client.getParams().setHttpElementCharset("GBK");

client.getHostConfiguration().setHost(host_url, 80, "http");

/*设置PostMethod */

PostMethod post=new PostMethod(login_url);

post.addRequestHeader("Accept", "*/*");

post.addRequestHeader("Accept-Encoding", "gzip, deflate");

post.addRequestHeader("Host", host_url);

post.addRequestHeader("Connection", "Keep-Alive");

/*设置http request的body值*/

post.setRequestBody(new NameValuePair[]{

new NameValuePair("__VIEWSTATE",viewstate),

new NameValuePair("textBox1",xh),

new NameValuePair("textBox2",pwd),

new NameValuePair("Button1",""),

new NameValuePair("lbLanguage","")

});

/*获取cookie*/

client.executeMethod(post);

Cookie cookies[]=client.getState().getCookies(); //得到cookies

for(int i=0; i

if(i==0) {

cookie=cookies[i].toString();

}

else {

cookie+=cookies[i]+";";

}

}

3.2 中文乱码问题的解决

在实际开发中,以上代码获得的content可能会出现中文乱码。在开发这类客户端时,中文编码往往是个很具难度的问题。由于中文网页的编码可能是UTF-8或GB2312格式的,如果没有采用对应的编码格式进行解析,则会产生乱码的问题。

据调查,80%以上的网页都没有设置response Header的charset,所以直接通过HttpClient获取charset是不可靠的;但是99%的网页设置了meta元素的charset,所以可以先根据一个默认编码(ISO-8859-1)获得HTML文档,再根据Jsoup或正则表达式获得该文档的charset。

因此以上代码中若有中文参数,可将

new NameValuePair("value_name" ,”中文”);

修改为

new NameValuePair("value_name", new String(“中文”.getBytes(),

"ISO-8859-1"));

3.3 访问所需页面

//设置所需访问的url

String mainUrl="/content.aspx;

//设置GetMethod

GetMethod get=new GetMethod(mainUrl);

//设置http Header,主重cookie信息

get.setRequestHeader("Accept-Language", "zh-CN");

get.setRequestHeader("Connection", "Keep-Alive");

get.setRequestHeader("Cache-Control", "no-cache");

get.setRequestHeader("Cookie", cookie);

//获取所需页面的html

client.executeMethod(get);

content=get.getResponseBodyAsString();

3.4 Android平台的移植

这一模块的实现需要运用到Jsoup技术,解析已经得到的html,从中获取需要的数据。以下代码是从上文的content中提取相关的通知标题,标题由标签等包含。

//将刚才的html转化成Document

Document document=Jsoup.parse(content);

//一个Document由elements组成

//选择”tr”开头的标签,存入 trs元素群中

Elements trs=document.select("tr");

for(int i=0; i

//观察HTML,从第i+2个tr开始,包含的才是我们要的信息

//从每个tr中选出td标签元素群

Elements tds=trs.get(i+2).select("td");

//得到每个tr中td的个数

int totalTds=tds.size();

//一个临时的HashMap,里面是String-Object键值对

Map map=new HashMap();

//j是一个标识数

for(int j=0; j

switch (j) {

//0表示第一个,即标题

//put方法即向map加入一条键值对

//html()方法就得到标签括起来的内容

case 0:

map.put("title", tds.get(j).html().toString());

break;

case 1:

//1表示第二个,即作者

map.put("author", tds.get(j).html().toString());

break;

default:

break;

}

}

list.add(map);

}

//list就是所需要的ArrayList

上面所有代码调试通过后,只需一些简单的复制、粘贴操作,就可以放在Android工程中,再加上一段简单的代码就可以让ListView显示这个ArrayList。

4 结束语

本文基于对HttpClint和Jsoup等技术的研究,成功实现了模拟登录网站,并从所需页面中提取有价值的信息,运用到Android设备中。通过本文所研究的方法,可以有效改善一般网站在移动设备上的体验不佳现状,从而提升其用户体验。虽然本文方法能够有效地应对目前大多数网站,但对于使用https协议的网站或者存在其他特殊验证的站点,还有一定的局限性。因此今后的研究方向是提高对多种网页结构的适应性,以及感知信息和网页结构的更新变化,同时减少其复杂性,提高其自动化和智能性。

参考文献:

[1] 洪辉,刘子敏.智能Web信息提取系统的研究和设计[J].微计算机信

息,2005.21(11).

[2] 罗刚,王振东.自己动手写网络爬虫[M].清华大学出版社,2010.

[3] http://hc.apache.org/httpclient-3.x

[4] 付聪.基于Smack库与HttpClient登陆的实现.中国科技论文在线,

2009.

[5] http://www.blogjava.net/Alpha/archive/2007/01/22/95216.html