使用 HttpClient 和 HtmlParser.docx
- 文档编号:30380137
- 上传时间:2023-08-14
- 格式:DOCX
- 页数:31
- 大小:111.82KB
使用 HttpClient 和 HtmlParser.docx
《使用 HttpClient 和 HtmlParser.docx》由会员分享,可在线阅读,更多相关《使用 HttpClient 和 HtmlParser.docx(31页珍藏版)》请在冰豆网上搜索。
使用HttpClient和HtmlParser
HttpClient与HtmlParser简介
本小结简单的介绍一下HttpClinet和HtmlParser两个开源的项目,以及他们的网站和提供下载的地址。
HttpClient简介
HTTP协议是现在的因特网最重要的协议之一。
除了WEB浏览器之外,WEB服务,基于网络的应用程序以及日益增长的网络计算不断扩展着HTTP协议的角色,使得越来越多的应用程序需要HTTP协议的支持。
虽然JAVA类库.net包提供了基本功能,来使用HTTP协议访问网络资源,但是其灵活性和功能远不能满足很多应用程序的需要。
而JakartaCommonsHttpClient组件寻求提供更为灵活,更加高效的HTTP协议支持,简化基于HTTP协议的应用程序的创建。
HttpClient提供了很多的特性,支持最新的HTTP标准,可以访问这里了解更多关于HttpClinet的详细信息。
目前有很多的开源项目都用到了HttpClient提供的HTTP功能,登陆网址可以查看这些项目。
本文中使用HttpClinet提供的类库来访问和下载Internet上面的网页,在后续部分会详细介绍到其提供的两种请求网络资源的方法:
Get请求和Post请求。
Apatche提供免费的HTTPClient源码和JAR包下载,可以登陆这里下载最新的HttpClient组件。
笔者使用的是HttpClient3.1。
HtmlParser简介
当今的Internet上面有数亿记的网页,越来越多应用程序将这些网页作为分析和处理的数据对象。
这些网页多为半结构化的文本,有着大量的标签和嵌套的结构。
当我们自己开发一些处理网页的应用程序时,会想到要开发一个单独的网页解析器,这一部分的工作必定需要付出相当的精力和时间。
事实上,做为JAVA应用程序开发者,HtmlParser为其提供了强大而灵活易用的开源类库,大大节省了写一个网页解析器的开销。
HtmlParser是上活跃的一个开源项目,它提供了线性和嵌套两种方式来解析网页,主要用于html网页的转换(Transformation)以及网页内容的抽取(Extraction)。
HtmlParser有如下一些易于使用的特性:
过滤器(Filters),访问者模式(Visitors),处理自定义标签以及易于使用的JavaBeans。
正如HtmlParser首页所说:
它是一个快速,健壮以及严格测试过的组件;以它设计的简洁,程序运行的速度以及处理Internet上真实网页的能力吸引着越来越多的开发者。
本文中就是利用HtmlParser里提取网页里的链接,实现简易爬虫里的关键部分。
HtmlParser最新的版本是HtmlParser1.6,可以登陆这里下载其源码、API参考文档以及JAR包。
回页首
开发环境的搭建
笔者所使用的开发环境是EclipseEuropa,此开发工具可以在www.eclipse.org免费的下载;JDK是1.6,你也可以在站点下载,并且在操作系统中配置好环境变量。
在Eclipse中创建一个JAVA工程,在工程的BuildPath中导入下载的Commons-httpClient3.1.Jar,htmllexer.jar以及htmlparser.jar文件。
图1.开发环境搭建
回页首
HttpClient基本类库使用
HttpClinet提供了几个类来支持HTTP访问。
下面我们通过一些示例代码来熟悉和说明这些类的功能和使用。
HttpClient提供的HTTP的访问主要是通过GetMethod类和PostMethod类来实现的,他们分别对应了HTTPGet请求与HttpPost请求。
GetMethod
使用GetMethod来访问一个URL对应的网页,需要如下一些步骤。
1.生成一个HttpClinet对象并设置相应的参数。
2.生成一个GetMethod对象并设置响应的参数。
3.用HttpClinet生成的对象来执行GetMethod生成的Get方法。
4.处理响应状态码。
5.若响应正常,处理HTTP响应内容。
6.释放连接。
清单1的代码展示了这些步骤,其中的注释对代码进行了较详细的说明。
清单1.
/*1生成HttpClinet对象并设置参数*/
HttpClienthttpClient=newHttpClient();
//设置Http连接超时为5秒
httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(5000);
/*2生成GetMethod对象并设置参数*/
GetMethodgetMethod=newGetMethod(url);
//设置get请求超时为5秒
getMethod.getParams().setParameter(HttpMethodParams.SO_TIMEOUT,5000);
//设置请求重试处理,用的是默认的重试处理:
请求三次
getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
newDefaultHttpMethodRetryHandler());
/*3执行HTTPGET请求*/
try{
intstatusCode=httpClient.executeMethod(getMethod);
/*4判断访问的状态码*/
if(statusCode!
=HttpStatus.SC_OK)
{
System.err.println("Methodfailed:
"+getMethod.getStatusLine());
}
/*5处理HTTP响应内容*/
//HTTP响应头部信息,这里简单打印
Header[]headers=getMethod.getResponseHeaders();
for(Headerh:
headers)
System.out.println(h.getName()+""+h.getValue());*/
//读取HTTP响应内容,这里简单打印网页内容
byte[]responseBody=getMethod.getResponseBody();//读取为字节数组
System.out.println(newString(responseBody));
//读取为InputStream,在网页内容数据量大时候推荐使用
InputStreamresponse=getMethod.getResponseBodyAsStream();//
…
}
catch(HttpExceptione)
{
//发生致命的异常,可能是协议不对或者返回的内容有问题
System.out.println("Pleasecheckyourprovidedhttpaddress!
");
e.printStackTrace();
}
catch(IOExceptione)
{
//发生网络异常
e.printStackTrace();
}finally{
/*6.释放连接*/
getMethod.releaseConnection();
}
这里值得注意的几个地方是:
1.设置连接超时和请求超时,这两个超时的意义不同,需要分别设置。
2.响应状态码的处理。
3.返回的结果可以为字节数组,也可以为InputStream,而后者在网页内容数据量较大的时候推荐使用。
在处理返回结果的时候可以根据自己的需要,进行相应的处理。
如笔者是需要保存网页
到本地,因此就可以写一个saveToLocaleFile(byte[]data,StringfilePath)的方法,将字节数组保存成本地文件。
后续的简易爬虫部分会有相应的介绍。
PostMethod
PostMethod方法与GetMethod方法的使用步骤大体相同。
但是由于PostMethod使用的是HTTP的Post请求,因而请求参数的设置与GetMethod有所不同。
在GetMethod中,请求的参数直接写在URL里,一般以这样形式出现:
http:
//hostname:
port//file?
name1=value1&name2=value…。
请求参数是name,value对。
比如我想得到XX搜索“ThinkingInJava”的结果网页,就可以使GetMethod的构造方法中的url为:
。
而PostMethod则可以模拟网页里表单提交的过程,通过设置表单里post请求参数的值,来动态的获得返回的网页结果。
清单2中的代码展示了如何创建一个Post对象,并设置相应的请求参数。
清单2
PostMethodpostMethod=newPostMethod("
postMethod.setRequestBody(newNameValuePair[]{newNameValuePair("q","java")});
回页首
HtmlParser基本类库使用
HtmlParser提供了强大的类库来处理Internet上的网页,可以实现对网页特定内容的提取和修改。
下面通过几个例子来介绍HtmlParser的一些使用。
这些例子其中的代码,有部分用在了后面介绍的简易爬虫中。
以下所有的代码和方法都在在类HtmlParser.Test.java里,这是笔者编写的一个用来测试HtmlParser用法的类。
∙迭代遍历网页所有节点
网页是一个半结构化的嵌套文本文件,有类似XML文件的树形嵌套结构。
使用HtmlParser可以让我们轻易的迭代遍历网页的所有节点。
清单3展示了如何来实现这个功能。
清单3
//循环访问所有节点,输出包含关键字的值节点
publicstaticvoidextractKeyWordText(Stringurl,Stringkeyword){
try{
//生成一个解析器对象,用网页的url作为参数
Parserparser=newParser(url);
//设置网页的编码,这里只是请求了一个gb2312编码网页
parser.setEncoding("gb2312");
//迭代所有节点,null表示不使用NodeFilter
NodeListlist=parser.parse(null);
//从初始的节点列表跌倒所有的节点
processNodeList(list,keyword);
}catch(ParserExceptione){
e.printStackTrace();
}
}
privatestaticvoidprocessNodeList(NodeListlist,Stringkeyword){
//迭代开始
SimpleNodeIteratoriterator=list.elements();
while(iterator.hasMoreNodes()){
Nodenode=iterator.nextNode();
//得到该节点的子节点列表
NodeListchildList=node.getChildren();
//孩子节点为空,说明是值节点
if(null==childList)
{
//得到值节点的值
Stringresult=node.toPlainTextString();
//若包含关键字,则简单打印出来文本
if(result.indexOf(keyword)!
=-1)
System.out.println(result);
}//endif
//孩子节点不为空,继续迭代该孩子节点
else
{
processNodeList(childList,keyword);
}//endelse
}//endwile
}
上面的中有两个方法:
1.privatestaticvoidprocessNodeList(NodeListlist,Stringkeyword)
该方法是用类似深度优先的方法来迭代遍历整个网页节点,将那些包含了某个关键字的值节点的值打印出来。
1.publicstaticvoidextractKeyWordText(Stringurl,Stringkeyword)
该方法生成针对String类型的url变量代表的某个特定网页的解析器,调用1中的方法实现简单的遍历。
清单3的代码展示了如何迭代所有的网页,更多的工作可以在此基础上展开。
比如找到某个特定的网页内部节点,其实就可以在遍历所有的节点基础上来判断,看被迭代的节点是否满足特定的需要。
∙使用NodeFilter
NodeFilter是一个接口,任何一个自定义的Filter都需要实现这个接口中的booleanaccept()方法。
如果希望迭代网页节点的时候保留当前节点,则在节点条件满足的情况下返回true;否则返回false。
HtmlParse里提供了很多实现了NodeFilter接口的类,下面就一些笔者所用到的,以及常用的Filter做一些介绍:
1.对Filter做逻辑操作的Fitler有:
AndFilter,NotFilter,OrFilter,XorFilter。
这些Filter来组合不同的Filter,形成满足两个Filter逻辑关系结果的Filter。
1.判断节点的孩子,兄弟,以及父亲节点情况的Filter有:
HasChildFilterHasParentFilter,HasSiblingFilter。
2.判断节点本身情况的Filter有HasAttributeFilter:
判读节点是否有特定属性;LinkStringFilter:
判断节点是否是具有特定模式(pattern)url的节点;
TagNameFilter:
判断节点是否具有特定的名字;NodeClassFilter:
判读节点是否是某个HtmlParser定义好的Tag类型。
在org.htmlparser.tags包下有对应Html标签的各种Tag,例如LinkTag,ImgeTag等。
还有其他的一些Filter在这里不一一列举了,可以在org.htmlparser.filters下找到。
清单4展示了如何使用上面提到过的一些filter来抽取网页中的标签里的href属性值,标签里的src属性值,以及标签里的src的属性值。
清单4
//获取一个网页上所有的链接和图片链接
publicstaticvoidextracLinks(Stringurl){
try{
Parserparser=newParser(url);
parser.setEncoding("gb2312");
//过滤标签的filter,用来提取frame标签里的src属性所、表示的链接
NodeFilterframeFilter=newNodeFilter(){
publicbooleanaccept(Nodenode){
if(node.getText().startsWith("framesrc=")){
returntrue;
}else{
returnfalse;
}
}
};
//OrFilter来设置过滤标签,标签和标签,三个标签是or的关系
OrFilterorFilter=newOrFilter(newNodeClassFilter(LinkTag.class),new
NodeClassFilter(ImageTag.class));
OrFilterlinkFilter=newOrFilter(orFilter,frameFilter);
//得到所有经过过滤的标签
NodeListlist=parser.extractAllNodesThatMatch(linkFilter);
for(inti=0;i Nodetag=list.elementAt(i); if(taginstanceofLinkTag)//标签 { LinkTaglink=(LinkTag)tag; StringlinkUrl=link.getLink();//url Stringtext=link.getLinkText();//链接文字 System.out.println(linkUrl+"**********"+text); } elseif(taginstanceofImageTag)//标签 { ImageTagimage=(ImageTag)list.elementAt(i); System.out.print(image.getImageURL()+"********");//图片地址 System.out.println(image.getText());//图片文字 } else//标签 { //提取frame里src属性的链接如 Stringframe=tag.getText(); intstart=frame.indexOf("src="); frame=frame.substring(start); intend=frame.indexOf(""); if(end==-1) end=frame.indexOf(">"); frame=frame.substring(5,end-1); System.out.println(frame); } } }catch(ParserExceptione){ e.printStackTrace(); } } ∙简单强大的StringBean 如果你想要网页中去掉所有的标签后剩下的文本,那就是用StringBean吧。 以下简单的代码可以帮你解决这样的问题: 清单5 StringBeansb=newStringBean(); sb.setLinks(false);//设置结果中去点链接 sb.setURL(url);//设置你所需要滤掉网页标签的页面url System.out.println(sb.getStrings());//打印结果 HtmlParser提供了强大的类库来处理网页,由于本文旨在简单的介绍,因此只是将与笔者后续爬虫部分有关的关键类库进行了示例说明。 感兴趣的读者可以专门来研究一下HtmlParser更为强大的类库。 回页首 简易爬虫的实现 HttpClient提供了便利的HTTP协议访问,使得我们可以很容易的得到某个网页的源码并保存在本地;HtmlParser提供了如此简便灵巧的类库,可以从网页中便捷的提取出指向其他网页的超链接。 笔者结合这两个开源包,构建了一个简易的网络爬虫。 爬虫(Crawler)原理 学过数据结构的读者都知道有向图这种数据结构。 如下图所示,如果将网页看成是图中的某一个节点,而将网页中指向其他网页的链接看成是这个节点指向其他节点的边,那么我们很容易将整个Internet上的网页建模成一个有向图。 理论上,通过遍历算法遍历该图,可以访问到Internet上的几乎所有的网页。 最简单的遍历就是宽度优先以及深度优先。 以下笔者实现的简易爬虫就是使用了宽度优先的爬行策略。 图2.网页关系的建模图 简易爬虫实现流程 在看简易爬虫的实现代码之前,先介绍一下简易爬虫爬取网页的流程。 图3.爬虫流程图 各个类的源码以及说明 对应上面的流程图,简易爬虫由下面几个类组成,各个类职责如下: Crawler.java: 爬虫的主方法入口所在的类,实现爬取的主要流程。 LinkDb.java: 用来保存已经访问的url和待爬取的url的类,提供url出对入队操作。 Queue.java: 实现了一个简单的队列,在LinkDb.java中使用了此类。 FileDownloader.java: 用来下载url所指向的网页。 HtmlParserTool.java: 用来抽取出网页中的链接。 LinkFilter.java: 一个接口,实现其accept()方法用来对抽取的链接进行过滤。 下面是各个类的源码,代码中的注释有比较详细的说明。 清单6Crawler.java packagecom.ie; importjava.util.Set; publicclassCrawler{ /*使用种子url初始化URL队列*/ privatevoidinitCrawlerWithSeeds(String[]seeds) { for(inti=0;i LinkDB.addUnvisitedUrl(seeds[i]); } /*爬取方法*/ publicvoidcrawling(String[]seeds) { LinkFilterfilter=newLinkFilter(){ //提取以开头的链接
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 使用 HttpClient HtmlParser