国产日韩欧美一区二区三区三州_亚洲少妇熟女av_久久久久亚洲av国产精品_波多野结衣网站一区二区_亚洲欧美色片在线91_国产亚洲精品精品国产优播av_日本一区二区三区波多野结衣 _久久国产av不卡

?

基于HttpClient的Android客戶端的設(shè)計與實現(xiàn)

2014-04-29 06:12:42王超閭陳莉吳迪項英杰
計算機(jī)時代 2014年3期

王超 閭陳莉 吳迪 項英杰

摘 要: 移動設(shè)備的普及和移動互聯(lián)網(wǎng)的高速發(fā)展讓人們開始依賴通過移動設(shè)備獲取信息,但普通頁面在移動端的體驗很難滿足用戶的需求。為此研究了HttpClient和Jsoup等技術(shù),分析了一般網(wǎng)站的登錄原理,成功實現(xiàn)了對一般網(wǎng)站的模擬登錄和頁面信息的提取,在此基礎(chǔ)上實現(xiàn)的系統(tǒng)可以在目標(biāo)網(wǎng)站中獲取用戶所需的信息,并將這些信息整合應(yīng)用到Android平臺,從而設(shè)計出用戶體驗更佳的網(wǎng)站Android客戶端。

關(guān)鍵詞: HttpClient; Jsoup; Android; 模擬登錄

中圖分類號:TP311 文獻(xiàn)標(biāo)志碼:A 文章編號:1006-8228(2014)03-30-03

0 引言

客戶端(Client)或稱為用戶端,是指與服務(wù)器相對應(yīng),為客戶提供本地服務(wù)的程序。而Android系統(tǒng)上90%的客戶端軟件具有一個共性:為了改善網(wǎng)頁在Android系統(tǒng)上體驗不佳而生。這類軟件最突出的特點是:先有網(wǎng)站再有客戶端。由于網(wǎng)絡(luò)技術(shù)發(fā)展的多樣性,手機(jī)瀏覽器往往無法跟隨它的步伐,為改善用戶體驗,網(wǎng)站客戶端軟件應(yīng)運(yùn)而生。

由于一般網(wǎng)站不提供服務(wù)端的開放平臺,我們無法調(diào)用所提供的API接口來開發(fā),所以需要對頁面信息進(jìn)行處理分析。在對網(wǎng)頁信息進(jìn)行處理分析時,不可能采用瀏覽器人工閱覽的方法,因此需要自己編寫分析處理程序,提取出有用的信息,為進(jìn)一步分析做準(zhǔn)備。由于原始HTML頁面的數(shù)據(jù)格式并不適合進(jìn)行處理[1],本研究將結(jié)合HttpClient與Jsoup對HTML頁面進(jìn)行抓取解析。

1 開發(fā)工具與環(huán)境的介紹

1.1 HttpClient

網(wǎng)頁抓取,就是把URL地址中指定的網(wǎng)絡(luò)資源從網(wǎng)絡(luò)流中讀取出來,保存到本地。類似于使用程序模擬IE瀏覽器的功能,把URL作為HTTP請求的內(nèi)容發(fā)送到服務(wù)器端,然后讀取服務(wù)器端的相應(yīng)資源[2]。雖然java.net包中已經(jīng)提供了訪問HTTP協(xié)議的基本功能,但是對于大部分應(yīng)用程序來說還不夠豐富和靈活。

HttpClient[3]是Apache Jakarta Common下的子項目,用來提供高效的、最新的、功能豐富的、支持HTTP協(xié)議的客戶端編程工具包,并且支持HTTP協(xié)議最新的版本和建議。HttpClient能夠處理HTTP連接中的各種問題,使用十分方便,只需導(dǎo)入HttpClient.jar包,就可以模擬IE瀏覽器來獲取網(wǎng)頁內(nèi)容。

1.2 Jsoup

Jsoup分析網(wǎng)頁結(jié)構(gòu)和內(nèi)容的功能遠(yuǎn)遠(yuǎn)強(qiáng)大于HtmlParser,無論是獲取整個頁面的文本,還是分析特定內(nèi)容的網(wǎng)頁結(jié)構(gòu),都十分方便。Jsoup數(shù)據(jù)獲取有兩大方法:①通過分析dom模型的網(wǎng)頁標(biāo)簽和元素;②select元素選擇器,類似Jquery方式。

1.3 Android

Android是一種基于Linux的自由及開放源代碼的操作系統(tǒng),主要適用于移動設(shè)備,如智能手機(jī)和平板電腦,由Google公司和開放手機(jī)聯(lián)盟領(lǐng)導(dǎo)及開發(fā)。2011年第一季度,Android在全球的市場份額首次超過塞班系統(tǒng),躍居全球第一。2012年11月的數(shù)據(jù)顯示,Android占據(jù)全球智能手機(jī)操作系統(tǒng)市場76%的份額,中國市場占有率為90%。在2013年09月24日Android操作系統(tǒng)迎來5歲生日時,全球采用這款系統(tǒng)現(xiàn)有設(shè)備數(shù)量已經(jīng)達(dá)到10億臺。

2 網(wǎng)站客戶端開發(fā)的設(shè)計

2.1 獲取數(shù)據(jù)的原理

圖1是一個簡單的示意圖,告訴我們,數(shù)據(jù)是由網(wǎng)頁從數(shù)據(jù)庫中取出,要為這個系統(tǒng)做客戶端,就應(yīng)該按照該數(shù)據(jù)獲取的原理去改造它,如圖2所示。

[網(wǎng)頁] [數(shù)據(jù)]

圖1 網(wǎng)頁從數(shù)據(jù)庫中提取數(shù)據(jù)

[安卓客戶端][網(wǎng)頁] [數(shù)據(jù)]

圖2 客戶端間接訪問數(shù)據(jù)庫

通過這樣間接的方法來訪問數(shù)據(jù)庫,只要網(wǎng)頁能看到的內(nèi)容,我們的客戶端都能獲取到,而UI是由用戶自行制作,可以使用戶體驗上一個臺階。

2.2 HttpClient模擬登錄原理

現(xiàn)如今不論是網(wǎng)站還是論壇,又或是一般的信息管理系統(tǒng),登錄功能都是必不可少的。因此我們?nèi)粝胍L問所需要的網(wǎng)站并從中獲取數(shù)據(jù),登錄是無法跳過的一個環(huán)節(jié)[4]。

因為HTTP協(xié)議是無狀態(tài)的,也就是連接的有效期只限于當(dāng)前請求,請求內(nèi)容結(jié)束后連接就關(guān)閉了。在這種情況下為了保存用戶的登錄信息必須使用Cookie機(jī)制[5]。以JSP/Servlet為例,當(dāng)瀏覽器請求一個JSP或者是Servlet頁面時,應(yīng)用服務(wù)器會返回一個參數(shù),名為jsessionid(因不同應(yīng)用服務(wù)器而異),其值是一個較長的惟一字符串的Cookie,這個字符串也就是當(dāng)前訪問該站點的會話標(biāo)識。瀏覽器每在訪問該站點的其他頁面時都要帶上jsessionid這樣的Cookie信息,應(yīng)用服務(wù)器根據(jù)這個會話標(biāo)識來獲取對應(yīng)的會話信息。

對于需要用戶登錄的網(wǎng)站,一般在用戶登錄成功后會將用戶資料保存在服務(wù)器的會話中,當(dāng)訪問其他的頁面時,應(yīng)用服務(wù)器根據(jù)瀏覽器送上的Cookie讀取當(dāng)前請求對應(yīng)的會話標(biāo)識以獲得對應(yīng)的會話信息,然后就可以判斷用戶資料是否存在于會話信息中,如果存在則允許訪問頁面,否則跳轉(zhuǎn)到登錄頁面中要求用戶輸入帳號和口令進(jìn)行登錄。這就是一般使用JSP開發(fā)的網(wǎng)站在處理用戶登錄時比較通用的方法。

對于HTTP的客戶端而言,如果要訪問一個受保護(hù)的頁面,就必須模擬瀏覽器所做的工作,首先是請求登錄頁面,讀取Cookie值;其次是請求登錄頁面并加入登錄頁所需的每個參數(shù);最后是請求最終所需的頁面。當(dāng)然,除第一次請求之外,其他的請求都需要附帶上Cookie信息以便服務(wù)器能判斷當(dāng)前請求是否已經(jīng)通過驗證。

在本研究中,通過HttpClient,可以方便地模擬出登錄的http請求,并獲取已經(jīng)通過驗證的Cookie,之后再通過該Cookie來進(jìn)行所需頁面的http請求,最終獲取其數(shù)據(jù)。雖然HttpClient自身具有自動調(diào)去Cookie的機(jī)制,但仍建議能夠自行調(diào)用代碼傳送Cookie。

3 網(wǎng)站客戶端的實現(xiàn)

本次模擬登錄和頁面信息獲取是在Java項目中完成的,由于Java項目可以完美移植到Android項目中,方便被調(diào)試,而且模擬Http請求這一過程并沒有用到任何Android功能。運(yùn)用HttpClient和 Jsoup技術(shù)的版本是HttpClient 3.x和Jsoup 1.6。

3.1 模擬登錄實現(xiàn)

/*對HttpClient 的初始化*/

private HttpClient client;

client=new HttpClient();

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

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

/*設(shè)置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");

/*設(shè)置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 中文亂碼問題的解決

在實際開發(fā)中,以上代碼獲得的content可能會出現(xiàn)中文亂碼。在開發(fā)這類客戶端時,中文編碼往往是個很具難度的問題。由于中文網(wǎng)頁的編碼可能是UTF-8或GB2312格式的,如果沒有采用對應(yīng)的編碼格式進(jìn)行解析,則會產(chǎn)生亂碼的問題。

據(jù)調(diào)查,80%以上的網(wǎng)頁都沒有設(shè)置response Header的charset,所以直接通過HttpClient獲取charset是不可靠的;但是99%的網(wǎng)頁設(shè)置了meta元素的charset,所以可以先根據(jù)一個默認(rèn)編碼(ISO-8859-1)獲得HTML文檔,再根據(jù)Jsoup或正則表達(dá)式獲得該文檔的charset。

因此以上代碼中若有中文參數(shù),可將

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

修改為

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

"ISO-8859-1"));

3.3 訪問所需頁面

//設(shè)置所需訪問的url

String mainUrl="/content.aspx;

//設(shè)置GetMethod

GetMethod get=new GetMethod(mainUrl);

//設(shè)置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平臺的移植

這一模塊的實現(xiàn)需要運(yùn)用到Jsoup技術(shù),解析已經(jīng)得到的html,從中獲取需要的數(shù)據(jù)。以下代碼是從上文的content中提取相關(guān)的通知標(biāo)題,標(biāo)題由標(biāo)簽等包含。

//將剛才的html轉(zhuǎn)化成Document

Document document=Jsoup.parse(content);

//一個Document由elements組成

//選擇”tr”開頭的標(biāo)簽,存入 trs元素群中

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

for(int i=0; i

//觀察HTML,從第i+2個tr開始,包含的才是我們要的信息

//從每個tr中選出td標(biāo)簽元素群

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

//得到每個tr中td的個數(shù)

int totalTds=tds.size();

//一個臨時的HashMap,里面是String-Object鍵值對

Map map=new HashMap();

//j是一個標(biāo)識數(shù)

for(int j=0; j

switch (j) {

//0表示第一個,即標(biāo)題

//put方法即向map加入一條鍵值對

//html()方法就得到標(biāo)簽括起來的內(nèi)容

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

上面所有代碼調(diào)試通過后,只需一些簡單的復(fù)制、粘貼操作,就可以放在Android工程中,再加上一段簡單的代碼就可以讓ListView顯示這個ArrayList。

4 結(jié)束語

本文基于對HttpClint和Jsoup等技術(shù)的研究,成功實現(xiàn)了模擬登錄網(wǎng)站,并從所需頁面中提取有價值的信息,運(yùn)用到Android設(shè)備中。通過本文所研究的方法,可以有效改善一般網(wǎng)站在移動設(shè)備上的體驗不佳現(xiàn)狀,從而提升其用戶體驗。雖然本文方法能夠有效地應(yīng)對目前大多數(shù)網(wǎng)站,但對于使用https協(xié)議的網(wǎng)站或者存在其他特殊驗證的站點,還有一定的局限性。因此今后的研究方向是提高對多種網(wǎng)頁結(jié)構(gòu)的適應(yīng)性,以及感知信息和網(wǎng)頁結(jié)構(gòu)的更新變化,同時減少其復(fù)雜性,提高其自動化和智能性。

參考文獻(xiàn):

[1] 洪輝,劉子敏.智能Web信息提取系統(tǒng)的研究和設(shè)計[J].微計算機(jī)信

息,2005.21(11).

[2] 羅剛,王振東.自己動手寫網(wǎng)絡(luò)爬蟲[M].清華大學(xué)出版社,2010.

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

[4] 付聰.基于Smack庫與HttpClient登陸的實現(xiàn).中國科技論文在線,

2009.

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

岳阳市| 栾城县| 肥城市| 林周县| 剑河县| 儋州市| 灌云县| 麟游县| 龙岩市| 清苑县| 龙游县| 年辖:市辖区| 南澳县| 新巴尔虎右旗| 紫阳县| 无极县| 安国市| 海伦市| 武平县| 苏州市| 怀集县| 云安县| 白水县| 甘谷县| 临洮县| 麻江县| 开封县| 石景山区| 图木舒克市| 横山县| 九台市| 黄大仙区| 衡阳市| 庆安县| 天峨县| 铁力市| 牟定县| 锡林郭勒盟| 田东县| 名山县| 雷山县|