httpclient與htmlparser等技術(shù)札記這是開(kāi)發(fā)遠(yuǎn)程數(shù)據(jù)時(shí)學(xué)的新知識(shí)記錄_第1頁(yè)
httpclient與htmlparser等技術(shù)札記這是開(kāi)發(fā)遠(yuǎn)程數(shù)據(jù)時(shí)學(xué)的新知識(shí)記錄_第2頁(yè)
httpclient與htmlparser等技術(shù)札記這是開(kāi)發(fā)遠(yuǎn)程數(shù)據(jù)時(shí)學(xué)的新知識(shí)記錄_第3頁(yè)
httpclient與htmlparser等技術(shù)札記這是開(kāi)發(fā)遠(yuǎn)程數(shù)據(jù)時(shí)學(xué)的新知識(shí)記錄_第4頁(yè)
httpclient與htmlparser等技術(shù)札記這是開(kāi)發(fā)遠(yuǎn)程數(shù)據(jù)時(shí)學(xué)的新知識(shí)記錄_第5頁(yè)
已閱讀5頁(yè),還剩87頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

第1/88 本書(shū)由JavaEye提供的DIY功能自動(dòng)生成于2009-01-—#! #!#2008-12-08關(guān)鍵字:Http是ApacheJakartaCommon下的子項(xiàng)目,可以用來(lái)提供高效的、的、功能豐富的支持HTTP協(xié)議的客戶端編程工具包,并且它支持HTTP協(xié)議的版本和建議。本文首先介紹HTTP,然后根據(jù)作Http基本功能的使^╳_▄42?使用Http需要以下6個(gè)步驟創(chuàng)建Http的實(shí)GetMethod。在GetMethodexecutemethod讀Httphttp=newHttp創(chuàng)建GET方法的實(shí)例。在GET方法的構(gòu)造函數(shù)中傳入待連接的地址即可。用GetMethod將會(huì)自動(dòng)處理轉(zhuǎn)發(fā)過(guò)程,如果想要把自動(dòng)處理轉(zhuǎn)發(fā)過(guò)程去掉的話,可以調(diào)用方法setFwRedirects(f)。GetMethodgetMethod=new 調(diào)用實(shí)例http的execteMethod方法來(lái)執(zhí)行g(shù)etMethod。由于是執(zhí)行在網(wǎng)絡(luò)上的程序,在運(yùn)行cethod方法的時(shí)候,需要處理兩個(gè)異常,分別是tinIOExcion。引起第一種異常的原因主要可能是在構(gòu)造getMethod的時(shí)候傳入的協(xié)議不對(duì),比如不將"http"寫(xiě)成"htp",務(wù)回的內(nèi)容不正常等,并且該異常發(fā)生是不可恢復(fù)的;第二種異常一般是由于網(wǎng)絡(luò)原因引起的異常,對(duì)于這種異常(IOExcin),Http會(huì)根據(jù)你指定的恢復(fù)策略自動(dòng)試著重新執(zhí)行executeMethod方法。Http的恢復(fù)策略可以自定義(通過(guò)實(shí)現(xiàn)接口HttpMethodRetryHandlr來(lái)實(shí)現(xiàn))。通過(guò)http的方法setParametr設(shè)置你實(shí)現(xiàn)的恢復(fù)策略,本文中使用的是系統(tǒng)提供的默認(rèn)恢復(fù)策略,該策略在碰到第二類(lèi)異常的時(shí)候?qū)⒆詣?dòng)重試3次。excuteMethod返回值是一個(gè)整數(shù),表示了執(zhí)行該方法后服務(wù)器返回的狀態(tài)碼,該狀態(tài)碼能表示出該方法執(zhí)行是否成功、需要認(rèn)證或者頁(yè)面發(fā)生了跳轉(zhuǎn)(默認(rèn)狀態(tài)下GetMethod的實(shí)例是自動(dòng)處理跳轉(zhuǎn)的)等。newintstatusCode=if(statusCode!=HttpStatus.SC_OK)System.err.println("Methodfailed:"+}在返回的狀態(tài)碼正確后,即可取得內(nèi)容。取得目標(biāo)地址的內(nèi)容有三種方法:第一種,getResponsBody,該方法返回的是目標(biāo)的二進(jìn)制的byte流;第二種,getRespBodyAsStig,這個(gè)方法返回的是String類(lèi)型,值得注意的是該方法返回的String的編碼是根據(jù)系統(tǒng)默認(rèn)的編碼方式,所以返回的String值可能編碼類(lèi)型有誤,在本文的"字符編碼"部分中將對(duì)此做詳細(xì)介紹;第三種,getRespeyAsStream,這個(gè)方法對(duì)于目標(biāo)地址中有大量數(shù)據(jù)需要傳輸是最佳的。在這里我們使用了最簡(jiǎn)單的getRespeBody方法。byte[]responseBody=packageimport publicclassGetSample{publicstaticvoidmain(String[]args) http=newHttpGetMethodgetMethod=new newDefaultHttpMethodRetryHandler());tryintstatusCode=http if(statusCode!=HttpStatus.SC_OK){System.err.println("Methodfailed:+}byte[]responseBody=System.out.println(new}catch(HttpExceptione)System.out.println("Pleasecheckyourprovidedhttpaddress!");}catch(IOExceptione)}finally}}}根據(jù)RFC26,對(duì)POST的解釋如下:POST方法用來(lái)向目的服務(wù)器發(fā)出請(qǐng)求,要求它接受被附在請(qǐng)求后的實(shí)體,并把它當(dāng)作請(qǐng)求隊(duì)列(Requetie)中請(qǐng)求URI所指定資源的附加新子項(xiàng)。POST被設(shè)計(jì)成用統(tǒng)一的方法實(shí)現(xiàn)下列功能:對(duì)現(xiàn)有資源的注釋?zhuān)ˋnnotationofexisting調(diào)用Http中的PostMethd與GetMethod類(lèi)似,除了設(shè)置Posthd的實(shí)例與GetMethod有些不同之外,剩下的步驟都差不多。在下面的例子中,省去了與GetMethod相同的步驟,只說(shuō)明與上面不同的地方,并以登錄BBS為例子進(jìn)行說(shuō)明。構(gòu)造PostMd之前的步驟都相同,與GetMethod一樣,構(gòu)造PotMethod也需要一個(gè)URI參數(shù),在本例中,登錄的地址是。在創(chuàng)建了PostMethod的實(shí)例之后,需要給method實(shí)例填充表單的值,在BBS的登錄表單中需要有兩個(gè)域,第一個(gè)是用戶名(叫id),二是(叫paswd)。表單中的域用類(lèi)NmeValuePair來(lái)表示,該類(lèi)的構(gòu)造函數(shù)第一個(gè)參數(shù)是,第二參數(shù)是該域的值;將表單所有的值設(shè)置到PostMethod中用方法sBody。另外由于BBS登錄成功后會(huì)轉(zhuǎn)向另外一個(gè)頁(yè)面,但是Http 對(duì)于要求接受后繼服務(wù)的請(qǐng)求,比如POT和PUT,不支持自動(dòng)轉(zhuǎn)發(fā),因此需要自己對(duì)頁(yè)面轉(zhuǎn)向做處理。具體的頁(yè)面轉(zhuǎn)向處理請(qǐng)參見(jiàn)下面的"自動(dòng)轉(zhuǎn)向"部分。代碼如下:Stringurl="PostMethodpostMethod=newNameValuePair[]data={newNameValuePair("id","youUserName"),newNameValuePair("passwd","yourPwd")};postMethodintstatusCode= // //301或者if(statusCode==HttpStatus.SC_MOVED_PERMANENTLY||statusCode==HttpStatus.SC_MOVED_TEMPORARILY){HeaderlocationHeader=postMethod.getResponseHeader("location");Stringlocation=null;if(locationHeader!=null)location=locationHeader.getValue();System.out.println("Thepagewasredirectedto:"+location);}elseSystem.err.println("Locationfieldvalueis}}某目標(biāo)頁(yè)的編碼可能出現(xiàn)在兩個(gè)地方,第一個(gè)地方是服務(wù)器返回的http頭中,另外一個(gè)地方是得到的l頁(yè)面中。Type:text/html;charset=UTF-8。這個(gè)頭信息表明該頁(yè)的編碼是UTF-8,但是服務(wù)器返回的頭信息未必與內(nèi)容能匹配上。比如對(duì)于一些雙字節(jié)語(yǔ)言國(guó)家,可能服務(wù)器返回的編碼類(lèi)型是UTF-8,但真正的內(nèi)容卻不是UTF-8編碼的,因此需要在另外的地方去得到頁(yè)面的編碼信息;但是如果服務(wù)器返回的編碼不是UTF-8,而是具體的一些對(duì)于象xml或者h(yuǎn)tml這樣的文件,允許作者在頁(yè)面中直接指定編碼類(lèi)型。比如在html中會(huì)有<metahttp-equiv="Content-Type"content="text/html;charset=gb2312"/>這樣的;或者在xml中會(huì)有<?xmlversion="1.0"encoding="gb2312"?>這樣的,在這些情況下,可能與http頭中返回的編碼信息,需privatestaticfinalStringCONTENT_CHARSET="GBK";//http內(nèi)容時(shí)使用的字符 =new 字符串編碼改變的方法:Stringtarget=newString(orig.getBytes("ISO-8859-Http三種不同的認(rèn)證方案:Basic,DigestandNTLM.這些方案可用于服務(wù)器或?qū)蛻舳说恼J(rèn)證,簡(jiǎn)服務(wù)器認(rèn)證(Server 處理服務(wù)器認(rèn)證幾乎是透明的,僅需要開(kāi)發(fā)人員提供登錄信息(logincredentials)。登錄信息保存在HttpState類(lèi)的實(shí)例中,可以通過(guò)setCredentials(Stringrealm,Credentialscred)和getCredentials(Stringrealm)來(lái)獲取或設(shè)置。注意,設(shè)定對(duì)非特定站點(diǎn)所需要的登錄信息,將realm參數(shù)置為null.Http 證,可以通過(guò)HttpMethod類(lèi)的setDoAuthentication(booleandoAuthentication)方法關(guān)閉,而且這次關(guān)閉在這種模式時(shí),Http 會(huì)主動(dòng)將basic認(rèn)證應(yīng)答信息傳給服務(wù)器,即使在某種情況下服務(wù)器可能返回認(rèn)證失敗的應(yīng)答,這樣做主要是為了減少連接的建立。為使每個(gè)新建的HttpStat實(shí)例都實(shí)行搶先認(rèn)證,可以如下設(shè)置系統(tǒng)屬性。setSystemProperty(Authenticator.PREEMPTIVE_PROPERTY,"true"); 2)認(rèn)證 除了登錄信息需單獨(dú)存放以外,認(rèn)證與服務(wù)器認(rèn)證幾乎一致。用setCredentials(Stringrealm,Credentialscred)和getCredentials(Stringrealm)設(shè)、取登錄信息。認(rèn)證方案(authentication是HTTP中規(guī)定最早的也是最兼容(?)的方案,遺憾的是也是最不安全的一個(gè)方案,因?yàn)樗悦鞔a傳送用戶名和密碼。它要求一個(gè)UsernamsswrdCredeias實(shí)例,可以指定服務(wù)器端的空間或采用默認(rèn)的登錄信息。igest是在HTTP.1中增加的一個(gè)方案,雖然不如Bac得到的軟件支持多,但還是有廣泛的使用。Digest方案比c方案安全得多,因它根本就不通過(guò)網(wǎng)絡(luò)傳送實(shí)際的,傳送的是利用這個(gè)對(duì)從服務(wù)器傳來(lái)的一個(gè)隨機(jī)數(shù)(nonce的加密串。它要求一個(gè)UserPaswrdredeils實(shí)例,可以指定服務(wù)器端的空間或采用默認(rèn)的登錄信息。這是Http支持的最復(fù)雜的認(rèn)證協(xié)議。它M$設(shè)計(jì)的一個(gè)私有協(xié)議,沒(méi)有公開(kāi)的規(guī)范說(shuō)明。一開(kāi)始由于設(shè)計(jì)的缺陷,NTM的安全性比Digest差,后來(lái)經(jīng)過(guò)一個(gè)Sik補(bǔ)丁后,安全性則比較Digest高。NTLM需要一個(gè)NTredentils實(shí)例.注意,由于NTLM不使用空間(rea)的概念,Http利用服務(wù)器的作訪問(wèn)空間的名字。還需要注意,提供給NTredeils的用戶名,不要用的前綴-如:""是正確的,而 \"則是錯(cuò)的.NTLM認(rèn)證的工作機(jī)制與basic和digest有很大的差別。這些差別一般由 從 API的角度來(lái)看,NTLM與其它認(rèn)證方式一樣的工作,差別是需要提供'NTCredentials'實(shí)例而不'UserePsswrdCredenia'(其實(shí),前者只是擴(kuò)展了后者)NTLM認(rèn)證,空間是連接到的機(jī)器的域名,這對(duì)多主機(jī)會(huì)有一些麻煩.只有Http 連接中指定的才是認(rèn)證用的。建議將realm設(shè)為null以使用默認(rèn)的設(shè)置。NTM只是認(rèn)證了接而不是一請(qǐng)求,所以每當(dāng)一個(gè)新的連接建立就要進(jìn)行一次認(rèn)證,且在認(rèn)證的過(guò)程中保持連接是非常重要的。因此,NTLM不能同時(shí)用于認(rèn)證和服務(wù)器認(rèn)證,也不能用于http.0連接或服務(wù)器不支持持久連接的情況。由于技術(shù)限制,以及為保證.0發(fā)布版API的穩(wěn)定,Http還不能自動(dòng)處重定向,但對(duì)重定向到同一主機(jī)、同一端口且采用同一協(xié)議的情況Http可以支持。不能自動(dòng)的處理的情況,包括需要人工交互的情況,或超出http的能力。301302303SeeOther.307當(dāng)收到簡(jiǎn)單的重定向時(shí),程序應(yīng)從HttpMethod對(duì)象中抽取新的URL并將其。另,限制一下重定向次數(shù)是個(gè)好的主意,這可以避免遞歸循環(huán)。新的URL可以從頭字段Location中抽取,如下:StringHeaderlocationHeader=method.getResponseHeader("location");if(locationHeader!=null){redirectLocation=}else//Theresponseisinvalidanddidnotprovidethenewlocation//theresource.Reportanerrororpossiblyhandlethe//likea404NotFound}300304HttpStatus.SC_NO305使用.根據(jù)RFC26中對(duì)自動(dòng)轉(zhuǎn)向的定義,主要有兩種: 和 。 表示永久的移走(MovedPermanely),當(dāng)返回的是1,則表示請(qǐng)求的資源已經(jīng)被移到一個(gè)固定的新地方,任何向該地址發(fā)起請(qǐng)求都會(huì)被轉(zhuǎn)到新的地址上。02表示暫時(shí)的轉(zhuǎn)向,比如在服務(wù)器端的servlt程序調(diào)用了sendReirec方法,則在客戶端就會(huì)得到一個(gè)32的代碼,這時(shí)服務(wù)器返回的頭信息中l(wèi)ocation的值就是seedrect轉(zhuǎn)向的目標(biāo)地址。p支持自動(dòng)轉(zhuǎn)向處理,但是象POSTPUT方式這種要求接受后繼服務(wù)的請(qǐng)求方式,暫時(shí)不支持自動(dòng)轉(zhuǎn)向,因此如果碰到POST方式提交后返回的是01或者02的話需要自己處理。就像剛才在POSThod中舉的例子:如果想進(jìn)入登錄BBS后的頁(yè)面,必須重新發(fā)起登錄的請(qǐng)求,請(qǐng)求的地址可以在頭字段location過(guò)需要注意的是,有時(shí)候location返回的可能是相對(duì)路徑,因此需要對(duì)location返回的值做一些處理才可以發(fā)起向新地址的請(qǐng)求。另外除了在頭中包含的信息可能使頁(yè)面發(fā)生重定向外,在頁(yè)面中也有可能會(huì)發(fā)生頁(yè)面的重定向。引起頁(yè)面自動(dòng)轉(zhuǎn)發(fā)的是:<metahtequiv="reres"5;l= ">。如果你想在程序中也處理這種情況的話得自己分析頁(yè)面來(lái)實(shí)現(xiàn)轉(zhuǎn)向。需要注意的是,在上面那個(gè)中url的值也可以是一個(gè)相對(duì)地址,如果是這樣的話,需要對(duì)它做一些處理后才可以轉(zhuǎn)發(fā)。 能自動(dòng)管理,包括允許服務(wù)器設(shè)置并在需要的時(shí)候自動(dòng)將 后發(fā)送到服務(wù)器端。不幸的是,對(duì)如何處理,有幾個(gè)規(guī)范互相:Netscape草案,RFC2109,RFC2965,而且還有很大數(shù)量的軟件商的 實(shí)現(xiàn)不遵循任何規(guī)范.為了處理這種狀 提供了策略驅(qū)動(dòng)的管理方式。Http 規(guī)范有:Netscape草案,是最早的 規(guī)范,基于rfc19。盡管這個(gè)規(guī)范與rc109有較大的差別,這樣做可以與一些服務(wù)器兼容。rfc109,是wc發(fā)布的第一個(gè)規(guī)范。理論上講,所有的服務(wù)器在處理 (版1)時(shí),都要遵循此規(guī)范,正因如此,Http將其設(shè)為默認(rèn)的規(guī)范。遺憾的是,這個(gè)規(guī)范太嚴(yán)格了,以致很多服務(wù)器不正確的實(shí)施了該規(guī)范或仍在作用Nescae規(guī)范。在這種情況下,應(yīng)使用兼容規(guī)范。兼容性規(guī)范,設(shè)計(jì)用來(lái)兼容盡可能多的服務(wù)器,即使它們并沒(méi)有遵循。當(dāng)解析 出現(xiàn)問(wèn)題時(shí),應(yīng)考慮采用兼容性規(guī)范。RFC2965規(guī)范暫時(shí)沒(méi)有被Http支持(在以后的版本為會(huì)加上),它定義了版本2,并說(shuō)明了 newHttp new spec", 用一個(gè)瀏覽器服務(wù)器,以確認(rèn)服務(wù)器應(yīng)答正常如果在使,關(guān)掉試試另找一個(gè)服務(wù)器來(lái)試試(如果運(yùn)行著不同的服務(wù)器軟件更好)檢查代碼是否按中講的思路編寫(xiě)設(shè)置log級(jí)別為debug,題原因打開(kāi)wiretrace,來(lái)追蹤客戶端與服務(wù)器的通信,以確實(shí)問(wèn)題出現(xiàn)在什么地方用 nt或netcat手工將信息發(fā)送到服務(wù)器,適合于猜測(cè)已經(jīng)找到了原因而進(jìn)行試驗(yàn)時(shí)將netcat以方式運(yùn)行,用作服務(wù)器以檢查http 試試,bug可能在的版本中修復(fù)了向郵件列表求幫助向bugzilla報(bào)借助JavaSecureSocketExtension(JSSE),Http 全面支持SecureSocketsLayer(SSL)或IETFTransportLayerSecurity(TLS)協(xié)議上的HTTP。JSSE已經(jīng)jre1.4及以后的版本中,以前的版本則需要手工安裝設(shè)置,具體過(guò)程參見(jiàn)Sun或本學(xué)習(xí)筆記。 =new GetMethodhttpget=newGetMethod("https: Httphttp=newHttp();http.getHostConfiguration().set("my host",8080);http.getState().setCredentials("my- -realm","my newUsernamePasswordCredentials("my- -username","my- GetMethodhttpget=newGetMethod("https: factory。這個(gè)socketfactory負(fù)責(zé)打一個(gè)到服務(wù)器的端口,使用標(biāo)準(zhǔn)的或第的SSL函數(shù)庫(kù),并進(jìn)行象連接https),一個(gè)定制的socketfactory,和一個(gè)默認(rèn)的端中號(hào)(如https的443端口).Protocolmyhttps=newProtocol("https",newMySSLSocketFactory(),443);然后,這個(gè)實(shí)例可被設(shè)置為協(xié)議的處理器。Httphttp =newHttp ",443,myhttps);GetMethodhttpget=newGetMethod("/"); 通過(guò)調(diào)用Protocl.regiterProtcl方法,將此定制的實(shí)例,為某一特定協(xié)議的默認(rèn)的處理器。由此,可以很方便地定制自己的協(xié)議類(lèi)型(如myhttps)。newProtocol("https",newMySSLSocketFactory(), =new GetMethodhttpget=newGetMethod("myhttps: newProtocol("https",newMySSLSocketFactory(),443)); =newHttp GetMethodhttpget=newGetMethod("https: 已知的限制和問(wèn)題持續(xù)的SSL連接在Sun的低于.4JM上不能工作,這是由于JVMbg造成。通過(guò)服務(wù)器時(shí),非搶先認(rèn)證(No-preemptieautheniion)會(huì)失敗,這是由于Http 的設(shè)計(jì)缺陷造成的,以后的版本中會(huì)修改。importjava.io.BufferedReader;importjava.io.InputStreamReader;importjava.io.OutputStreamWriter;importjava.io.Writer;.ssl.SSLSocketFactory;publicclassTest{publicstaticfinalStringTARGET_HTTPS_SERVER=" publicstaticfinalintTARGET_HTTPS_PORT=443;publicstaticvoidmain(String[]args)throws{Socketsocket=SSLSocketFactory.getDefault().createSocket(TARGET_HTTPS_SERVER,TARGET_HTTPS_PORT);tryWriterout=OutputStreamWriter(socket.getOutputStream(),"ISO-8859-1");out.write("GET/out.write("Host:"+TARGET_HTTPS_SERVER+":"+TARGET_HTTPS_PORT+"\r\n");out.write("Agent:SSL-TEST\r\n");BufferedReaderin=newnewInputStreamReader(socket.getInputStream(),"ISO-8859-1"));Stringline=null;while((line=in.readLine())!={}}finally}}}使用多線程的主要目的,是為了實(shí)現(xiàn)并行的。在http運(yùn)行的過(guò)程中,每個(gè)http協(xié)議的方法,使用一pConnein實(shí)例。由于連接是一種有限的資源,每個(gè)連接在某一時(shí)刻只能供一個(gè)線程和方法使用,所以需要確保在需要時(shí)正確地分配連接。Http 采用了一種類(lèi)似jdbc連接池的方法來(lái)管理連接,這個(gè)管理工作由liHttpConnecinManager完成。MultiThreadedHttpConnectionManagerconnectionManager=newMultiThreadedHttpConnectionManager();Http=newHttp此是,可以在多個(gè)線程中被用來(lái)執(zhí)行多個(gè)方法。每次調(diào)用Http.executeMethod()方法,都會(huì)去器。管理器支持兩個(gè)設(shè)置:maxConnectionsPerHost每個(gè)主機(jī)的最大并行數(shù),默認(rèn)為2maxTotalConnections客戶端總并行最大數(shù),默認(rèn)為20管理器重新利用時(shí),采取早歸還者先重用的方式(leastrecentlyusedapproach)。 MultiThreadedHttpConnectionManagerconnectionManager=newHttp=newHttpGetMethodget=newGetMethod("");try{//printresponsetostdout}finally//besuretheconnectionisreleasedbacktothe//manager} 在method.rleaseConi)后并沒(méi)有把關(guān)閉,這個(gè)方法只是將返回給connectionmanager。如果使用Http =wp ()實(shí)例化一個(gè)p eionmanager默認(rèn)實(shí)現(xiàn)是使用{this.alwaysClose=}alwaysClose設(shè)為true在釋放之后connectionmanager就會(huì)關(guān)閉鏈。在我們Http=newHttp()這樣實(shí)例化一個(gè)時(shí)connectionmanager是這樣被實(shí)例化的this.httpConnectionManager=newSimpleHttpConnectionManager();因此alwaysClose默認(rèn)是fals,conin是不會(huì)被主動(dòng)關(guān)閉的,因此我們就有了一個(gè)客戶端關(guān)閉的方法。解決方法:manager會(huì)關(guān)閉connection。Http=newHttp(newHttpParams(),new2、實(shí)例化代碼使用:Http=newHttp();在method.releaseConnection();之后加publicvoidshutdown()} =newHttppublicvoidcloseIdleConnections(longidleTimeout){longmaxIdleTime=System.currentTimeMillis()-idleTimeout;if(idleStartTime<=maxIdleTime){}}method.setRequestHeader("Connection","close");importimportimport *用*@authorpublicclass{publicstaticvoidmain(String[]args)throwsHttp=newHttpGetMethodget=newGetMethod("http FilestoreFile=newFile("c:/2008FileOutputStreamoutput=new 23. 2008-12-08關(guān)鍵字:importjava.util.Map;importorg.htmlparser.Node;importorg.htmlparser.NodeFilter;importorg.htmlparser.Parser;importorg.htmlparser.tags.LinkTag;importorg.htmlparser.util.NodeList;importcom.yao.http.HttpRespons;*@authorpublicclassTestpublicstaticvoidmain(String[]{try/*首先我們先使用HttpRequester類(lèi)和HttpRespons類(lèi)獲得一個(gè)HTTP請(qǐng)求中的數(shù)據(jù)(HTML文檔)??梢詮腗ap<String,String>map=newHashMap<String,String>();HttpRequesterrequest=newHttpRequester();HttpResponshr=request.sendGet("ht Parserparser=Parser.createParser(hr.getContent(),hrtry//通過(guò)過(guò)濾器過(guò)濾出<A>NodeListnodeListparserpublicbooleanaccept(Nodeif(nodeinstanceofLinkTag)//標(biāo)returnfalse;}for(inti=0;i<nodeList.size();i++)LinkTagn=(LinkTag)nodeList.elementAt(i);System.out.print(n.getStringText()+"==>>");}}catch(Exception{}}catch(Exception{}}} 2008-12-08關(guān)鍵字:通過(guò)使用Log4,可以指定日志信息輸出的目的地,控制每一條日志的輸出格式,定義日志信息的級(jí)別。所有這些功能通過(guò)一個(gè)配置文件靈活進(jìn)行配置。...一個(gè)Logger可以有多個(gè)Appender,也就是說(shuō)日志信息可以同時(shí)輸出到多個(gè)設(shè)備上,每個(gè)Appender一種Layout(示例見(jiàn)下圖)。↗Appender1→/﹨↘Appender2→ packageorg.apache.log4j;publicclassLogger//Creation&retrievalmethods:publicstaticLoggergetRootLogger();publicstaticLoggergetLogger(String//printingpublicvoiddebug(Objectmessage);publicvoidinfo(Objectmessage);publicvoidwarn(Objectmessage);publicvoiderror(Objectmessage);publicvoidfatal(Objectmessage);//genericprintingpublicvoidlog(Priorityp,Object}一共有五種,級(jí)別由高到低依次是:fatal、error、warn、info、debug。獲得Logger調(diào)用以下方法之一輸出日志信息:publicvoiddebug(Objectmessage); publicvoidinfo(Objectmessage); //輸出info級(jí)別的日志信息;publicvoidwarn(Objectmessage); publicvoiderror(Objectmessage); publicvoidfatal(Objectmessage); publicvoidlog(Priorityp,Objectmessage);//輸出參數(shù)Priority以上方法只有當(dāng)它的級(jí)別大于或等于Logger組件配置的日志級(jí)別時(shí)才調(diào)用。以前面我們配置的myLogger為例,它的日志級(jí)別為WARN,那么在程序中,它的warn)、error()、fatal()方被執(zhí)行。對(duì)log有當(dāng)它的參數(shù)Priority指定的日志級(jí)別大于或等于WARN時(shí),它才會(huì)被執(zhí)行。在寫(xiě)程序的時(shí)候,為了調(diào)試程序,我們會(huì)在很多出錯(cuò)的地方輸出大量的日志信息。當(dāng)程序調(diào)試完,不需要這些信息時(shí),將程序中這些輸出日志信息代碼刪除嗎?這樣費(fèi)時(shí)費(fèi)力,對(duì)于大型程序幾乎不可行。通過(guò)對(duì)日志分級(jí),假如不想輸出WARN級(jí)別的日志信息,則Logger組件的級(jí)別調(diào)高即可,省時(shí)。Log4J提供了一個(gè)rootLogger,它是所有Logger組件的“祖先”,它存在,且不能通過(guò)名字檢索或引用,通過(guò)Logger.getRootLogger()方法取得它。配置rootLogger代碼:可在配置文件中方便地配置存在繼承關(guān)系的Logger前面的Loggr組件的子類(lèi)。例如:以上代碼中,mySonLogger是myLogger的子類(lèi)Logger組件。Logger.黙認(rèn)情況下,子類(lèi)Logger組件會(huì)繼承父類(lèi)所有的Appender,把它們加入到自己的Logger組件的additivity標(biāo)志設(shè)為false,那么它就不會(huì)繼承父類(lèi)Appender。additivity標(biāo)志默認(rèn)rootLogger:日志級(jí)別=INFOappender↑myLogger:日志級(jí)別=WARNappender↑mySonLogger:日志級(jí)別=nullappender rootLogger WARN .文件.GUI組件(GUI(Remotesocket.NT的記錄器(NTEvent.UNIXSyslog守護(hù)進(jìn)程(RemoteUNIXSyslog一個(gè)Logger可同時(shí)對(duì)應(yīng)多個(gè)Appender,示例:myLogger配置二個(gè)Appender:file,console:.org.apache.log4j.TTCCLayout(包含日志產(chǎn)生的時(shí)間、線程和類(lèi)別等信息);WARN-Thisisalogmessagefromthelog4j.appender.file.layout.ConversionPattern=%t%p%m%nTHREAD-1WARNThisisalogmessagefromthemyLogger J支持二種配置文件格式:XLJavaJava屬性文件格式配置文件:.配置Logger配置rootLogger語(yǔ)法為:.配置Appender配置日志信息輸出目的地Appender,語(yǔ)法為:.配置Layout下面為一配置文件示例,文件名為##LOGGERS#configurerootlogger#definealoggernamedmyLogger#defineasecondloggerthatisachildtomyLogger##APPENDERS#defineanappendernamedconsole,whichissettobeaConsoleAppender#defineanappendernamedfile,whichissettobeaRollingFileAppender##LAYOUTS#assianaSimpleLayouttoconsoleappender#assianaPatternLayouttofileappenderLoggermyLogger=.日志記錄器,配置Log4J環(huán)境自動(dòng)快速地使用默認(rèn)myLogger.debug("Thieisalogmessagefromthe"+importimportpublicclassTestpublicstaticvoidmain(String[]args)//GetaninstanceoftheLoggermyLogger=//GetaninstanceoftheLoggermySonLogger=//LoadtheproertiesusingthePropertyConfigurator//LogMessagesusingtheParentmyLogger.debug("Thieisalogmessagefromthe"+myLogger.getName());myL("Thieisalogmessagefromthe"+myLogger.getName());myLogger.warn("Thieisalogmessagefromthe"+myLogger.getName());myLogger.error("Thieisalogmessagefromthe"+myLogger.getName());myLogger.fatal("Thieisalogmessagefromthe"+myLogger.getName());mySonLogger.debug("Thieisalogmessagefromthe"+mySonLogger.getName());mySonL("Thieisalogmessagefromthe"+mySonLogger.getName());mySonLogger.warn("Thieisalogmessagefromthe"+mySonLogger.getName());mySonLogger.error("Thieisalogmessagefromthe"+mySonLogger.getName());mySonLogger.fatal("Thieisalogmessagefromthe"+mySonLogger.getName());}}WARN-ThieisalogmessagefromthemyLogger&;ERROR-ThieisalogmessagefromthemyLoggerFATAL-ThieisalogmessagefromthemyLoggerWARN-ThieisalogmessagefromthemyLogger.mySonLoggerERROR-ThieisalogmessagefromthemyLogger.mySonLoggerFATAL-ThieisalogmessagefromthemyLogger.mySonLogger另在Test.class所在的下看到一個(gè)log.txt文件,內(nèi)容如下:WARN-ThieisalogmessagefromthemyLogger.mySonLoggerERROR-ThieisalogmessagefromthemyLogger.mySonLoggerFATAL-ThieisalogmessagefromthemyLogger.mySonLoggerWARN-ThieisalogmessagefromthemyLoggerERROR-ThieisalogmessagefromthemyLoggerFATAL-ThieisalogmessagefromthemyLoggerWARN-ThieisalogmessagefromthemyLogger.mySonLoggerWARN-ThieisalogmessagefromthemyLogger.mySonLoggerERROR-ThieisalogmessagefromthemyLogger.mySonLoggerERROR-ThieisalogmessagefromthemyLogger.mySonLoggerFATAL-ThieisalogmessagefromthemyLogger.mySonLoggerFATAL-ThieisalogmessagefromthemyLogger.mySonLoggermySonLogger的日志在控制臺(tái)上輸出了二次,這是因?yàn)閙ySonLogger繼承了父類(lèi)consoleAppender,本身又定義了一個(gè)consoleAppender,因而有二個(gè)consoleAppender。創(chuàng)建一個(gè)Serlt,在它初始化方法中Log4J配置文件并配置Log4J環(huán)境,這個(gè)Srlt在Web應(yīng)用啟動(dòng)時(shí)候被加載和初始化,然后就可在其它Web組件中獲取Logger對(duì)象并輸出日志。importjavax.servlet.*;importjavax.servlet.http.*;importjava.io.*;importimportorg.apache.log4j.PropertyConfigurator;publicclassLog4JServletextends{publicvoidinit()throwsServletExceptionStringpath=Stringpropfile=path+getInitParameter("propfile");}}<%@pageLoggermyLogger=LoggermySonLogger=Logger.getLogger("myLogger.mySonLogger");myLogger.debug("Thieisalogmessagefromthe"+myLogger.getName());myL("Thieisalogmessagefromthe"+myLogger.getName());myLogger.warn("Thieisalogmessagefromthe"+myLogger.getName());myLogger.error("Thieisalogmessagefromthe"+myLogger.getName());myLogger.fatal("Thieisalogmessagefromthe"+myLogger.getName());mySonLogger.debug("Thieisalogmessagefromthe"+mySonLogger.getName());mySonL("Thieisalogmessagefromthe"+mySonLogger.getName());mySonLogger.warn("Thieisalogmessagefromthe"+mySonLogger.getName());mySonLogger.error("Thieisalogmessagefromthe"+mySonLogger.getName());mySonLogger.fatal("Thieisalogmessagefromthe"+mySonLogger.getName());<formname="loginForm"method="post"action="dispatcher">username:<inputtype="text"name="username">password:<inputtype="text"<inputtype="submit"name="submit" 創(chuàng)建Log4J的配置文件perties,存放 編譯Log4JServlet,存放 :<WEB應(yīng)用所 WARN-ThieisalogmessagefromthemyLoggerERROR-ThieisalogmessagefromthemyLoggerFATAL-ThieisalogmessagefromthemyLoggerWARN-ThieisalogmessagefromthemyLogger.mySonLoggerERROR-ThieisalogmessagefromthemyLogger.mySonLoggerFATAL-ThieisalogmessagefromthemyLogger.mySonLogger WARN-ThieisalogmessagefromthemyLogger.mySonLoggerERROR-ThieisalogmessagefromthemyLogger.mySonLoggerFATAL-ThieisalogmessagefromthemyLogger.mySonLogger#!&時(shí)間:2008-12-時(shí)間:2008-12-【】正則表達(dá)式是煩瑣的,但是強(qiáng)大的,學(xué)會(huì)之后的應(yīng)用會(huì)讓你除了提高效率外,會(huì)給你帶來(lái)成就感。只要認(rèn)真去閱讀這些資料,加上應(yīng)用的時(shí)候進(jìn)行一定的參考,掌握正則表達(dá)式不是問(wèn)題。1956年,一位叫StephenKleene的數(shù)學(xué)家在McCulloch和Pitts早期工作的基礎(chǔ)上,了一篇標(biāo)題為“神經(jīng)網(wǎng)的表示法”的,引入了正則表達(dá)式的概念。正則表達(dá)式就是用來(lái)描述他稱(chēng)為“正則集的代數(shù)”的表達(dá)式,因此采▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃#!目前,正則表達(dá)式已經(jīng)在很多軟件中得到廣泛的應(yīng)用,包括*nix(LinuxUnix等),HP等操作系統(tǒng),正則表達(dá)式的使用,可以通過(guò)簡(jiǎn)單的辦法來(lái)實(shí)現(xiàn)強(qiáng)大的功能。為了簡(jiǎn)單有效而又不失強(qiáng)大,造成了正則表達(dá)式代碼的難度較大,學(xué)習(xí)起來(lái)也不是很容易,所以需要付出一些努力才行,之后參照一定的參考,使用例子:這樣的代碼曾經(jīng)多次把給嚇退過(guò)??赡芎芏嗳艘彩潜贿@樣的代碼給嚇跑的吧。繼續(xù)閱讀本文將讓也可以自由應(yīng)用這樣的代碼。注意:這里的第7部分跟前面的內(nèi)容看起來(lái)似乎有些重復(fù),目的是把前面表格里的部分重新描述了一次,目的是讓這些內(nèi)容更容易理解。$!1956年,一位叫StephenKleene的數(shù)學(xué)家在McCulloch和Pitts早期工作的基礎(chǔ)上,了一篇標(biāo)題為 隨后,發(fā)現(xiàn)可以將這一工作應(yīng)用于使用KenThompson的計(jì)算搜索算法的一些早期研究,KenThompson是UnixUnix中的qed編輯器。如他們所說(shuō),剩下的就是眾所周知的歷史了。從那時(shí)起直至現(xiàn)在正則表達(dá)式都是基于文本的編輯器和搜索工具中的一個(gè)重要部分。%!正則表達(dá)式(regularexpression)描述了一種字符串匹配的模式,可以用來(lái)檢查一個(gè)串是否含有某串、 dir*.txt或ls*.txt中的*.txt就不是一個(gè)正則表達(dá)式,因?yàn)檫@里*與正則式的*的含義是不同的。正則表達(dá)式是由普通字符(例如字符a到z)以及特殊字符(稱(chēng)為元字符)組成的文字模式。正則表達(dá)式字符含義匹配由x\cMControl-MxA-Za-zc c' x0c\cL x0a\cJ x0d\cM \ x09\cI \x0b\cK所謂特殊字符,就是一些有特殊含義的字符,如上面說(shuō)的"*.txt"中的*,簡(jiǎn)單的說(shuō)就是表示任何字符串的意思。如果要查找文件名中有*的文件,則需要對(duì)*進(jìn)行轉(zhuǎn)義,即在其前加一個(gè)\。ls\txt。正則表達(dá)式有以下特殊字符。$RegExpMultiline$n'\r$$。)***n[標(biāo)記一個(gè)中括號(hào)表達(dá)式的開(kāi)始。要匹配[,請(qǐng)使用\[。\||\|構(gòu)造正則表達(dá)式的方法和創(chuàng)建數(shù)學(xué)表達(dá)式的方法一樣。也就是用多種元字符與操作符將小的表達(dá)式結(jié)合在一起來(lái)創(chuàng)建更大的表達(dá)式。正則表達(dá)式的組件可以是單個(gè)的字符、字符集合、字符范圍、字符間的選擇或者所有這些組件的任意組合。貪婪或最小匹配。字符描述 匹配前面的子表達(dá)式零次或多次。例如,zo*z"zoo"。*{0, 匹配前面的子表達(dá)式一次或多次。例如,'zo"zo""zoo""z"{1,} 匹配前面的子表達(dá)式零次或一次。例如,"do(es"do"does"do"0,1 nn'o{2}'"Bob"'ofoodo

mnnmnmo{1,3}"fooooood"o。'o?'用來(lái)描述字符串或單詞的邊界,^和$分別指字符串的開(kāi)始與結(jié)束,\b描述單詞的前或后邊界,\B詞邊界。不能對(duì)定位符使用限定符。其中:是非捕獲元之一,還有兩個(gè)非捕獲元是=和!,這兩個(gè)還有的含義,前者為正向預(yù)查,在任何開(kāi)始匹配圓括號(hào)內(nèi)的正則表達(dá)式模式的位置來(lái)匹配搜索字符串,后者為負(fù)向預(yù)查,在任何開(kāi)始不匹配該正則表達(dá)式模式的位置來(lái)匹配搜索字符串。對(duì)一個(gè)正則表達(dá)式模式或部分模式兩邊添加圓括號(hào)將導(dǎo)致相關(guān)匹配到一個(gè)臨時(shí)緩沖區(qū)中,所捕獲的每個(gè)子匹配都按照在正則表達(dá)式模式中從左至右所遇到的內(nèi)容。子匹配的緩沖區(qū)編號(hào)從1開(kāi)始,連續(xù)編號(hào)直至最大9個(gè)子表達(dá)式。每個(gè)緩沖區(qū)都可以使用'\',其中n為一個(gè)標(biāo)識(shí)特定緩沖區(qū)的一位或兩位十進(jìn)制數(shù)。or&!操作符描述 *n}n, ,\ '!\

RegExpMultiline,^\n'r' 匹配輸入字符串的結(jié)束位置。如果設(shè)置了RegExpMultiline,$\n'r' 匹配前面的子表達(dá)式零次或多次。例如,zo*z"zoo"。*{0, 匹配前面的子表達(dá)式一次或多次。例如,'zo"zo""zoo"z"{1,} 匹配前面的子表達(dá)式零次或一次。例如,"do(es"do"does"do"0,1 nn'o{2}'"Bob'ofoodo?

'o+'。'o{0,}''o*'mnnmnmo{1,3}"fooooood"o。'o{0,1}''o?'oooo",'o"o",而'o+'將匹配所有'o'。

式的各個(gè)部分是很有用。例如,'industr(?:y|ies)就是一個(gè)比'industry|industries'更簡(jiǎn)略的表達(dá)式。patternws=95|"Windos"Windw",但不能匹配"Winds1s"。預(yù)查不消耗字符,也就是說(shuō),在一個(gè)匹配發(fā)生后,在最后一次匹配之后立即開(kāi)始下一次匹配的搜索,而不是從使用。例如'Windows(?!95|98|NT|2000)'能匹配"Windows3.1"中的"Windows",但不能匹配"Windows2000"中的 匹配x或y。例如,'z|food'能匹配"z"或"food"。'(z|f)ood'則匹配"zood"或"food"。 字符集合。匹配所包含的任意一個(gè)字符。例如,'[abc]'可以匹配"in"中的'a'。 負(fù)值字符集合。匹配未包含的任意字符。例如,'[^abc]'可以匹配"in"中的'p'。 字符范圍。匹配指定范圍內(nèi)的任意字符。例如,'[a-z]'az 負(fù)值字符范圍。匹配任何不在指定范圍內(nèi)的任意字符。例如,'[^a-z]'az' 匹配非單詞邊界。'er\B"verb'er'"never"'er'x\cMControl-MxA-Za-zc c' x0c\cL x0a\cJ x0d\cM \ x09\cI \x0b\cK '\x04'&"1"ASCII 標(biāo)識(shí)一個(gè)八進(jìn)制轉(zhuǎn)義值或一個(gè)向后。如果\n之前至少n個(gè)獲取的子表達(dá)式,則n為向后。否則,如果n為八進(jìn)制

標(biāo)識(shí)一個(gè)八進(jìn)制轉(zhuǎn)義值或一個(gè)向后。如果\nm之前至少有nm個(gè)獲得子表達(dá)式,則nm為向后。如果\nm之前至匹配八進(jìn)制轉(zhuǎn)義值nm。 n0-3ml0-7),nml 匹配n,其中n是一個(gè)用四個(gè)十六進(jìn)制數(shù)字表示的Unicode字符。例如,\u00A9匹 (! # /Windows(?=95|98|NT )!一切從最基本的開(kāi)始。模式,是正規(guī)表達(dá)式最基本的元素,它們是一組描述字符串特征的字符。模式可以很簡(jiǎn)單,由普通的字符串組成,也可以非常復(fù)雜,往往用特殊的字符表示一個(gè)范圍內(nèi)的字符、重復(fù)出現(xiàn),或表示上下文。例如:串"onceuponatime"匹配,與"ThereoncewasamanfromNewYork"不匹配。正如如^符號(hào)表示開(kāi)頭一這個(gè)模式與"Whokeptallofthiscashinabucket"匹配,與"buckets"不匹配。字符^和$同時(shí)使用時(shí),ThereoncewasamanfromNewYorkWhokeptallofhiscashinabucket.在該模式中的字母(-c)是字面的字符,也就是說(shuō),他們表示該字母本身,數(shù)字也是一樣的。其他一些稍微復(fù)雜的字符,如標(biāo)點(diǎn)符號(hào)和白字符(空格、制表符等),要用到轉(zhuǎn)義序列。所有的轉(zhuǎn)義序列都用反斜杠(\)打頭。制表符的轉(zhuǎn)義序列是:\t。所以如果我們要檢測(cè)一個(gè)字符串是否以制表符開(kāi)頭,可以用這個(gè)模式:在INTERNET的程序中,正規(guī)表達(dá)式通常用來(lái)驗(yàn)證用戶的輸入。當(dāng)用戶提交一個(gè)FORM以后,要判斷輸入的、地址、 地址、號(hào)碼等是否有效,用普通的基于字面的字符是不夠的。所以要用一種更自由的描述我們要的模式的辦法,它就是字符簇。要建立一個(gè)表示所有元音字符的字符簇,就把所有的元音字符放在一個(gè)方括號(hào)里:[a-z]//匹配所有的小寫(xiě)字母[A-Z[a-zA-Z]//匹配所有的字母[0-9]//匹配所有的數(shù)字[0-9\.[\f\r\t\n]//匹配所有的白字符同樣的,這些也只表示一個(gè)字符,這是一個(gè)非常重要的。如果要匹配一個(gè)由一個(gè)小寫(xiě)字母和一位數(shù)字組成的字符串,比如"z"、"t"或"g7",但不是"ab"、"rd3"或"b2"的話,用這個(gè)模式:[^a-z]//除了小寫(xiě)字母以外的所有字符[^\\\/\^]^)之外的所有字符特殊字符"."(點(diǎn),句號(hào))在正規(guī)表達(dá)式中用來(lái)表示除了“新行”之外的所有字符。所以模式"^.$"與任何兩個(gè)字符的、以數(shù)字5結(jié)尾和以其他非“新行”字符開(kāi)頭的字符串匹配。模式"."可以匹配任何字符串,除了空串和只包括一個(gè)“新行”的字符串。[[:alpha:[[:digit:]][[:space:]][[:upper:]][[:lower:]][[:xdigit:]]任何16進(jìn)制的數(shù)字,相當(dāng)于[0-9a-fA-7.3到現(xiàn)在為止,你已經(jīng)知道如何去匹配一個(gè)字母或數(shù)字,但的情況下,可能要匹配一個(gè)單詞或一組數(shù)面的內(nèi)容的重復(fù)出現(xiàn)的次數(shù)。^[a-zA-Z_]$^[[:alpha:]]{3}$所有的3^a$字母^a{4}$^a{2,4}$aa,aaa或^a{1,3}$a,aa或^a{2,}$包含多于兩個(gè)a如:,}如:\t{2這些例子描述了花括號(hào)的三種不同的用法。一個(gè)數(shù)字,{x}的意思是“前面的字符或字符簇只出現(xiàn)x次”;一個(gè)數(shù)字加逗號(hào),{,}的意思是“前面的內(nèi)容出現(xiàn)x或的次數(shù)”;兩個(gè)用逗號(hào)分隔的數(shù)字,{,y}“內(nèi)容至少出現(xiàn)x次,但不超過(guò)y次”。我們可以把模式擴(kuò)展到的單詞或數(shù)字://所有的小數(shù)最后一個(gè)例子不太好理解,是嗎?這么看吧:與所有以一個(gè)可選的負(fù)號(hào)(\{0,1}開(kāi)頭(^)、跟著0個(gè)或的數(shù)字([{0,1})再跟上0個(gè)或多個(gè)數(shù)字([0。下面你將知道能夠使用的更為簡(jiǎn)單的方法。{0,1}是相等的,它們都代表著:“0個(gè)或1個(gè)前面的內(nèi)容”或“前面的內(nèi)容是可選的”。所以剛才的例子可以簡(jiǎn)化為:特殊字符"*"與{0,}是相等的,它們都代表著“0{1,}是相等的,!'時(shí)間:2008-12-時(shí)間:2008-12-需要做一個(gè)垂直搜索引擎,比較了nekohtml和htmlparsernekohtml在容錯(cuò)性、性能等方面的口碑好像比htmlparser好(htmlunit也用的是nekohtml),但感覺(jué)nekohtml的測(cè)試用例和文檔都比htmlparser的使用,有空再研究nekohtml和mozillahtmlparser的使用。HTMLHTMLParserisaJavalibraryusedtoparseHTMLineitheralinearornestedfashion.Primarilyusedfortransformationorextraction,itfeaturesfilters,visitors,customtagsandeasytouseJavaBeans.Itisafast,robustandwelltestedpackage.Thetwofundamentaluse-casesthatarehandledbytheparserareextractionandtransformation(thesynthesesuse-case,whereHTMLpagesarecreatedfromscratch,isbetterhandledbyothertoolsclosertothesourceofdata).Whilepriorversionsconcentratedondataextractionfromwebpages,Version1.4oftheHTMLParserhassubstantialimprovementsintheareaoftransformingwebpages,withsimplifiedtagcreationandediting,andverbatimtoHtml()methodoutput. * 取節(jié)點(diǎn)起始位置的方法:getStartPosition、getEndPositionVisitor方法遍歷節(jié)點(diǎn)時(shí)候方法:accept(NodeVisitorvisitor)Filter方法:collectIntoNodeListlistNodeFilterfilter)* *葉子節(jié)點(diǎn)HTMLParserisaJavalibraryusedtoparseHTMLineitheralinearornestedfashion.Primarilyusedfortransformationorextraction,itfeaturesfilters,visitors,customtagsandeasytouseJavaBeans.Itisafast,robustandwelltestedpackage.Thetwofundamentaluse-casesthatarehandledbytheparserareextractionandtransformation(thesynthesesuse-case,whereHTMLpagesarecreatedfromscratch,isbetterhandledbyothertoolsclosertothesourceofdata).Whilepriorversionsconcentratedondataextractionfromwebpages,Version1.4oftheHTMLParserhassubstantialimprovementsintheareaoftransformingwebpages,withsimplifiedtagcreationandediting,andverbatimtoHtml()methodoutput. *采用Visitor方式HtmlWU\Parserparser=RIZ NodeVisitorvisitor=RIZNodeVisitor()TXFPMGYSMHvisitTag(Tagtag)logger.fatal(”testVisitorAll()Tagnameis +tag.getTagName()+”\nClassis + 16. *采用Filter方式html20.WU\NodeFilterfilter=RIZParserparser=RIZ NodeListlist=LinkTagnode=(LinkTag)logger.fatal(”testLinkTag()Linkis:”+ 33. *采用org.htmlparser.beans 另外htmlparserorg.htmlparser.beansLinkBeanlinkBean=RIZ URL[]urls=linkBean.getLinks();URLurl=logger.fatal(”testLinkBean()-urlis:”+48. . htmlparser其實(shí)代碼并不多,好好研究一下其代碼,彌補(bǔ)文檔不足的問(wèn)題。同時(shí)htmlparser的代碼注釋和單元測(cè)試用例還是很齊全的,也有助于了解htmlparser的用法。56.3.1、 Parser.createParser(Stringhtml,StringcharsetParserParser(Lexerlexer,ParserFeedbackfb)、Parser(URLConnectionconnection,ParserFeedbackfb)Parser(Stringresource,ParserFeedbackfeedback)、Parser(String Parserparser=RIZParser JSU tori=parser.elements();i.hasMoreElements();processMyNodes(i.nextNode());*parse(NodeFilterfilter):通過(guò)NodeFilter*visitAllNodesWith(NodeVisitorvisitor):通過(guò)Nodevisitor*extractAllNodesThatMatchNodeFilterfilter):通過(guò)NodeFilter方式76.3.2、. 對(duì)Vir和lter的方法進(jìn)行了封裝,定義了針對(duì)一些常用html元素操作的bean,簡(jiǎn)化對(duì)常用元素的提取操作。 定義了htmlparser所提供的各種filter,主要通過(guò)extractAllNodesThatMatch(NodeFilterfilter)來(lái)HasAttributeFilter、HasChildFilter、HasParentFilter、HasSiblingFilter、IsEqualFilter、LinkRegexFilter、LinkStringFilter、NodeClassFilter、NotFilter、OrFilter、RegexFilter、 定義了htmlparser所提供的各種visitor,主要通過(guò)visitAllNodesWithNodeVisitorvisitor)來(lái)對(duì)ObjectFindingVisitor、StringFindingVisitor、TagFindingVisitor、TextExtractingVisitor、 定義了一些實(shí)用的工具,包括LinkExtractor、iteCapturr、StringExtrator、WiiCapturr,這幾個(gè)類(lèi)也可以作為htmlparsr使用樣例。MQTSUWMQTSUWMQTSUWMQTSUWMQTSUWMQTSUWMQTSUWMQTSUWMQTSUWMQTSUWMQTSUWMQTSUWMQTSUWMQTSUWMQTSUWMQTSUWMQTSUWMQTSUWMQTSUWMQTSUWMQTSUWMQTSUW MQTSUWMQTSUWMQTSUWMQTSUW TUMYEWIVWEWMGJMREPLoggerlogger=Logger.getLogger(ParserTestCase.GPEVV); *ObjectFindVisitorTXFPMGYSMHtestImageVisitor()WU\ImageTagObjectFindingVisitorvisitor=RIZParserparser=RIZ Node[]nodes=imgLink=(ImageTag)logger.fatal(”testImageVisitor()ImageURL= + logger.fatal(”testImageVisitor()ImageLocation= + logger.fatal(”testImageVisitor()SRC= + GEWGL(Exceptione) *測(cè)試TagNameFilterTXFPMGYSMHtestNodeFilter()WU\NodeFilterfilter=RIZParserparser=RIZ NodeListlist=logger.fatal(”testNodeFilter()”+ *測(cè)試NodeClassFilterTXFPMGYSMHtestLinkTag()WU\NodeFilterfilter=RIZParserparser=RIZ NodeListlist=LinkTagnode=(LinkTag)logger.fatal(”testLinkTag()Linkis:”+ *<linkhref=”text=’text/css’rel=’stylesheetTXFPMGYSMHtestLinkCSS()WU\Parserparser=RIZ +“<linkhref=’/test01/css.css’text=’text/css’rel=’stylesheet’ +“<linkhref=’/test02/css.css’text=’text/css’rel=’stylesheet’ +“</head>”+JSU tore=parser.elements();e.hasMoreNodes();)Nodenode=.fatal(”testLinkCSS()”+ + *測(cè)試OrFilterTXFPMGYSMHtestOrFilter()NodeFilterinputFilter=RIZNodeFilterselectFilter=RIZParserWU\Parserparser=RIZ +“<linkhref=’/test01/css.css’text=’text/css’rel=’stylesheet’ +“<linkhref=’/test02/css.css’text=’text/css’rel=’stylesheet’ + + +“<inputtype=’text’value=’text1′ +“<inputtype=’text’value=’text2′ +“<select><optionid=’1′>1</option><option +“<a +OrFilterlastFilter=RIZlastFilter.setPredicates(RIZNodeFilter[]{inputFilternodeList=MJ(nodeList.elementAt(i)MRVWERGISJInputTag)InputTa

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論