网络爬虫---htmlparser

packageparser;

importjava.io.BufferedReader;

importjava.io.BufferedWriter;

importjava.io.FileWriter;

importjava.io.IOException;

importjava.io.InputStream;

importjava.io.InputStreamReader;

importjava.net.MalformedURLException;

importjava.net.URL;

/**

*基本能实现网页抓取,不过要手动输入URL将整个html内容保存到指定文件

*

*@authorchenguoyong

*

*/

publicclassScrubSelectedWeb{

privatefinalstaticStringCRLF=System.getProperty("line.separator");

/**

*@paramargs

*/

publicstaticvoidmain(String[]args){

try{

URLur=newURL("http://10.249.187.199:8083/injs100/");

InputStreaminstr=ur.openStream();

Strings,str;

BufferedReaderin=newBufferedReader(newInputStreamReader(instr));

StringBuffersb=newStringBuffer();

BufferedWriterout=newBufferedWriter(newFileWriter(

"D:/outPut.txt"));

while((s=in.readLine())!=null){

sb.append(s+CRLF);

}

System.out.println(sb);

str=newString(sb);

out.write(str);

out.close();

in.close();

}catch(MalformedURLExceptione){

e.printStackTrace();

}catch(IOExceptione){

e.printStackTrace();

}

}

}

基本能实现网页抓取,不过要手动输入URL,此外没有重构。只是一个简单的思路。

1.htmlparser使用

htmlparser是一个纯的java写的html解析的库,htmlparser不依赖于其它的java库,htmlparser主要用于改造或提取htmlhtmlparser能超高速解析html,而且不会出错。毫不夸张地说,htmlparser就是目前最好的html解析和分析的工具。无论你是想抓取网页数据还是改造html的内容,用了htmlparser绝对会忍不住称赞。由于htmlparser结构设计精良,所以扩展htmlparser非常便利。

Htmlparser中文论坛.http://bbs.hexiao.cn/thread.php?fid=6

ConstructorSummary

Parser()

Parser(URLConnectionconnection)
ConstructaparserusingtheprovidedURLConnection.

Method:

staticParsercreateParser(Stringhtml,Stringcharset)
Createstheparseronaninputstring.

voidvisitAllNodesWith(NodeVisitorvisitor)
Applythegivenvisitortothecurrentpage.

HtmlPage(Parserparser)

NodeList

getBody()

TableTag[]

getTables()

String

getTitle()

void

setTitle(Stringtitle)

void

visitTag(Tagtag)
CalledforeachTagvisited.

ConstructorSummary

NodeList()

NodeList(Nodenode)
Createaoneelementnodelist.

NodeListextractAllNodesThatMatch(NodeFilterfilter)
Filterthelistwiththegivenfilternon-recursively.

NodeListextractAllNodesThatMatch(NodeFilterfilter,booleanrecursive)
Filterthelistwiththegivenfilter.

NodeelementAt(inti)

1.html代码里面所有的链接地址和链接名称

packageparser;

importorg.htmlparser.Parser;

importorg.htmlparser.Node;

importorg.htmlparser.NodeFilter;

importorg.htmlparser.Parser;

importorg.htmlparser.filters.TagNameFilter;

importorg.htmlparser.tags.LinkTag;

importorg.htmlparser.tags.TableTag;

importorg.htmlparser.util.NodeList;

importorg.htmlparser.util.ParserException;

importorg.htmlparser.visitors.HtmlPage;

/**

*htmlparser取得一段html代码里面所有的链接地址和链接名称

*

*@authorchenguoyong

*

*/

publicclassTesthtmlparser{

/**

*@paramargs

*/

publicstaticvoidmain(String[]args){

Stringhtmlcode="<HTML><HEAD><TITLE>AAA</TITLE></HEAD><BODY>"

+"<ahref='http://topic.csdn.net/u/20080522/14/0ff402ef-c382-499a-8213-ba6b2f550425.html'>连接1</a>"

+"<ahref='http://topic.csdn.net'>连接2</a></BODY></HTML>";

//创建Parser对象根据传给字符串和指定的编码

Parserparser=Parser.createParser(htmlcode,"GBK");

//创建HtmlPage对象HtmlPage(Parserparser)

HtmlPagepage=newHtmlPage(parser);

try{

//HtmlPageextendsvisitor,Applythegivenvisitortothecurrent

//page.

parser.visitAllNodesWith(page);

}catch(ParserExceptione1){

e1=null;

}

//所有的节点

NodeListnodelist=page.getBody();

//建立一个节点filter用于过滤节点

NodeFilterfilter=newTagNameFilter("A");

//得到所有过滤后,想要的节点

nodelist=nodelist.extractAllNodesThatMatch(filter,true);

for(inti=0;i<nodelist.size();i++){

LinkTaglink=(LinkTag)nodelist.elementAt(i);

//链接地址

System.out.println(link.getAttribute("href")+"\n");

//链接名称

System.out.println(link.getStringText());

}

}

}

结果如下:

http://topic.csdn.net/u/20080522/14/0ff402ef-c382-499a-8213-ba6b2f550425.html

连接1

http://topic.csdn.net

连接2

2.使用HtmlParser抓去网页内容

packageparser;

importorg.htmlparser.Parser;

importorg.htmlparser.beans.StringBean;

importorg.htmlparser.filters.NodeClassFilter;

importorg.htmlparser.parserapplications.StringExtractor;

importorg.htmlparser.tags.BodyTag;

importorg.htmlparser.util.NodeList;

importorg.htmlparser.util.ParserException;

/**

*使用HtmlParser抓去网页内容:要抓去页面的内容最方便的方法就是使用StringBean.里面有几个控制页面内容的几个参数.

*在后面的代码中会有说明.Htmlparser包中还有一个示例StringExtractor里面有个直接得到内容的方法,

*其中也是使用了StringBean.另外直接解析Parser的每个标签也可以的.

*

*@authorchenguoyong

*

*/

publicclassGetContent{

publicvoidgetContentUsingStringBean(Stringurl){

StringBeansb=newStringBean();

sb.setLinks(true);//是否显示web页面的连接(Links)

//为了取得页面的整洁美观一般设置上面两项为true,如果要保持页面的原有格式,如代码页面的空格缩进可以设置为false

sb.setCollapse(true);//如果是true的话把一系列空白字符用一个字符替代.

sb.setReplaceNonBreakingSpaces(true);//Iftrueregularspace

sb

.setURL("http://www.blogjava.net/51AOP/archive/2006/07/19/59064.html");

System.out.println("TheContentis:\n"+sb.getStrings());

}

publicvoidgetContentUsingStringExtractor(Stringurl,booleanlink){

//StringExtractor内部机制和上面的一样.做了一下包装

StringExtractorse=newStringExtractor(url);

Stringtext=null;

try{

text=se.extractStrings(link);

System.out.println("Thecontentis:\n"+text);

}catch(ParserExceptione){

e.printStackTrace();

}

}

publicvoidgetContentUsingParser(Stringurl){

NodeListnl;

try{

Parserp=newParser(url);

nl=p.parse(newNodeClassFilter(BodyTag.class));

BodyTagbt=(BodyTag)nl.elementAt(0);

System.out.println(bt.toPlainTextString());//保留原来的内容格式.包含js代码

}catch(ParserExceptione){

e.printStackTrace();

}

}

/**

*@paramargs

*/

publicstaticvoidmain(String[]args){

Stringurl="http://www.blogjava.net/51AOP/archive/2006/07/19/59064.html";

//newGetContent().getContentUsingParser(url);

//--------------------------------------------------

newGetContent().getContentUsingStringBean(url);

}

}

3.将整个html内容保存到指定文件

packageparser;

importjava.io.BufferedReader;

importjava.io.BufferedWriter;

importjava.io.FileWriter;

importjava.io.IOException;

importjava.io.InputStream;

importjava.io.InputStreamReader;

importjava.net.MalformedURLException;

importjava.net.URL;

/**

*基本能实现网页抓取,不过要手动输入URL将整个html内容保存到指定文件

*

*@authorchenguoyong

*

*/

publicclassScrubSelectedWeb{

privatefinalstaticStringCRLF=System.getProperty("line.separator");

/**

*@paramargs

*/

publicstaticvoidmain(String[]args){

try{

URLur=newURL("http://www.google.cn/");

InputStreaminstr=ur.openStream();

Strings,str;

BufferedReaderin=newBufferedReader(newInputStreamReader(instr));

StringBuffersb=newStringBuffer();

BufferedWriterout=newBufferedWriter(newFileWriter(

"D:/outPut.txt"));

while((s=in.readLine())!=null){

sb.append(s+CRLF);

}

System.out.println(sb);

str=newString(sb);

out.write(str);

out.close();

in.close();

}catch(MalformedURLExceptione){

e.printStackTrace();

}catch(IOExceptione){

e.printStackTrace();

}

}

}

4利用htmlparser提取网页纯文本的例子

packageparser;

importorg.htmlparser.Node;

importorg.htmlparser.NodeFilter;

importorg.htmlparser.Parser;

importorg.htmlparser.filters.TagNameFilter;

importorg.htmlparser.tags.TableTag;

importorg.htmlparser.util.NodeList;

/**

*标题:利用htmlparser提取网页纯文本的例子

*/

publicclassTestHTMLParser2{

/**

*读取目标html内容

*

*/

publicstaticvoidtestHtml(){

try{

StringsCurrentLine;

StringsTotalString;

sCurrentLine="";

sTotalString="";

java.io.InputStreaml_urlStream;

java.net.URLl_url=newjava.net.URL(

"http://10.249.187.199:8083/injs100/");

java.net.HttpURLConnectionl_connection=(java.net.HttpURLConnection)l_url

.openConnection();

l_connection.connect();

l_urlStream=l_connection.getInputStream();

java.io.BufferedReaderl_reader=newjava.io.BufferedReader(

newjava.io.InputStreamReader(l_urlStream));

while((sCurrentLine=l_reader.readLine())!=null){

sTotalString+=sCurrentLine+"\r\n";

}

StringtestText=extractText(sTotalString);

}catch(Exceptione){

e.printStackTrace();

}

}

/**

*抽取纯文本信息

*@paraminputHtmlhtml文本

*@return

*@throwsException

*/

publicstaticStringextractText(StringinputHtml)throwsException{

StringBuffertext=newStringBuffer();

Parserparser=Parser.createParser(newString(inputHtml.getBytes(),

"GBK"),"GBK");

//遍历所有的节点

NodeListnodes=parser.extractAllNodesThatMatch(newNodeFilter(){

publicbooleanaccept(Nodenode){

returntrue;

}

});

System.out.println(nodes.size());

for(inti=0;i<nodes.size();i++){

Nodenodet=nodes.elementAt(i);

//字符串的代表性节点:节点的描述

text.append(newString(nodet.toPlainTextString().getBytes("GBK"))

+"\r\n");

}

returntext.toString();

}

/**

*读取文件的方式/utl来分析内容.filePath也可以是一个Url.

*@paramresource:文件/Url

*@throwsException

*/

publicstaticvoidtest5(Stringresource)throwsException{

ParsermyParser=newParser(resource);

myParser.setEncoding("GBK");

StringfilterStr="table";

NodeFilterfilter=newTagNameFilter(filterStr);

NodeListnodeList=myParser.extractAllNodesThatMatch(filter);

/*for(inti=0;i<nodeList.size();i++)

{

TableTagtabletag=(TableTag)nodeList.elementAt(i);

//标签名称

System.out.println(tabletag.getTagName());

System.out.println(tabletag.getText());

}*/

TableTagtabletag=(TableTag)nodeList.elementAt(1);

}

publicstaticvoidmain(String[]args)throwsException{

test5("http://10.249.187.199:8083/injs100/");

//testHtml();

}

}

5.html解析table

packageparser;

importorg.apache.log4j.Logger;

importorg.htmlparser.NodeFilter;

importorg.htmlparser.Parser;

importorg.htmlparser.filters.NodeClassFilter;

importorg.htmlparser.filters.OrFilter;

importorg.htmlparser.filters.TagNameFilter;

importorg.htmlparser.tags.TableColumn;

importorg.htmlparser.tags.TableRow;

importorg.htmlparser.tags.TableTag;

importorg.htmlparser.util.NodeList;

importorg.htmlparser.util.ParserException;

importjunit.framework.TestCase;

publicclassParserTestCaseextendsTestCase{

privatestaticfinalLoggerlogger=Logger.getLogger(ParserTestCase.class);

publicParserTestCase(Stringname){

super(name);

}

/**

*测试对<table>

*<tr>

*<td></td>

*</tr>

*</table>的解析

*/

publicvoidtestTable(){

ParsermyParser;

NodeListnodeList=null;

myParser=Parser

.createParser(

"<body>"

+"<tableid=table1>"

+"<trid='tro1'><td>1-11</td><td>1-12</td><td>1-13</td></tr>"

+"<trid='tro2'><td>1-21</td><td>1-22</td><td>1-23</td></tr>"

+"<trid='tro3'><td>1-31</td><td>1-32</td><td>1-33</td></tr></table>"

+"<tableid=table2>"

+"<trid='tro4'><td>2-11</td><td>2-12</td><td>2-13</td></tr>"

+"<trid='tro5'><td>2-21</td><td>2-22</td><td>2-23</td></tr>"

+"<trid='tro6'><td>2-31</td><td>2-32</td><td>2-33</td></tr></table>"

+"</body>","GBK");

NodeFiltertableFilter=newNodeClassFilter(TableTag.class);

OrFilterlastFilter=newOrFilter();

lastFilter.setPredicates(newNodeFilter[]{tableFilter});

try{

nodeList=myParser.parse(lastFilter);

for(inti=0;i<=nodeList.size();i++){

if(nodeList.elementAt(i)instanceofTableTag){

TableTagtag=(TableTag)nodeList.elementAt(i);

TableRow[]rows=tag.getRows();

for(intj=0;j<rows.length;j++){

TableRowtr=(TableRow)rows[j];

System.out.println(tr.getAttribute("id"));

if(tr.getAttribute("id").equalsIgnoreCase("tro1")){

TableColumn[]td=tr.getColumns();

for(intk=0;k<td.length;k++){

//logger.fatal("<td>"+

//td[k].toPlainTextString());

System.out.println("<td>"

+td[k].toPlainTextString());

}

}

}

}

}

}catch(ParserExceptione){

e.printStackTrace();

}

}

/**

*得到目标数据

*

*@paramurl:目标url

*@throwsException

*/

publicstaticvoidgetDatabyUrl(Stringurl)throwsException{

ParsermyParser=newParser(url);

NodeListnodeList=null;

myParser.setEncoding("gb2312");

NodeFiltertableFilter=newNodeClassFilter(TableTag.class);

OrFilterlastFilter=newOrFilter();

lastFilter.setPredicates(newNodeFilter[]{tableFilter});

try{

nodeList=myParser.parse(lastFilter);

//可以从数据tablesize:19-21开始到结束

for(inti=15;i<=nodeList.size();i++){

if(nodeList.elementAt(i)instanceofTableTag){

TableTagtag=(TableTag)nodeList.elementAt(i);

TableRow[]rows=tag.getRows();

for(intj=0;j<rows.length;j++){

TableRowtr=(TableRow)rows[j];

if(tr.getAttribute("id")!=null

&&tr.getAttribute("id").equalsIgnoreCase(

"tr02")){

TableColumn[]td=tr.getColumns();

//对不起,没有你要查询的记录!

if(td.length==1){

System.out.println("对不起,没有你要查询的记录");

}else{

for(intk=0;k<td.length;k++){

System.out.println("<td>内容:"

+td[k].toPlainTextString().trim());

}

}

}

}

}

}

}catch(ParserExceptione){

e.printStackTrace();

}

}

/**

*测试已经得出有数据时table:22个,没有数据时table:19

*

*@paramargs

*/

publicstaticvoidmain(String[]args){

try{

//getDatabyUrl("http://gd.12530.com/user/querytonebytype.do?field=tonecode&condition=619505000000008942&type=1006&pkValue=619505000000008942");

getDatabyUrl("http://gd.12530.com/user/querytonebytype.do?field=tonecode&condition=619272000000001712&type=1006&pkValue=619272000000001712");

}catch(Exceptione){

e.printStackTrace();

}

}

}

6.html解析常用

packagecom.jscud.test;

importjava.io.BufferedReader;
importjava.io.File;
importjava.io.FileInputStream;
importjava.io.InputStreamReader;

importorg.htmlparser.Node;
importorg.htmlparser.NodeFilter;
importorg.htmlparser.Parser;
importorg.htmlparser.filters.NodeClassFilter;
importorg.htmlparser.filters.OrFilter;
importorg.htmlparser.nodes.TextNode;
importorg.htmlparser.tags.LinkTag;
importorg.htmlparser.util.NodeList;
importorg.htmlparser.util.ParserException;
importorg.htmlparser.visitors.HtmlPage;
importorg.htmlparser.visitors.TextExtractingVisitor;

importcom.jscud.util.LogMan;//一个日志记录类

/**
*演示了HtmlParse的应用.
*
*@authorscudhttp://www.jscud.com(http://www.jscud.com/)
*/

publicclassParseHtmlTest
{

publicstaticvoidmain(String[]args)throwsException
{
StringaFile="e:/jscud/temp/test.htm";

Stringcontent=readTextFile(aFile,"GBK");

test1(content);
System.out.println("====================================");

test2(content);
System.out.println("====================================");

test3(content);
System.out.println("====================================");

test4(content);
System.out.println("====================================");

test5(aFile);
System.out.println("====================================");

//访问外部资源,相对慢
test5("http://www.jscud.com(http://www.jscud.com/)");
System.out.println("====================================");

}

/**
*读取文件的方式来分析内容.
*filePath也可以是一个Url.
*
*@paramresource文件/Url
*/
publicstaticvoidtest5(Stringresource)throwsException
{
ParsermyParser=newParser(resource);

//设置编码
myParser.setEncoding("GBK");

HtmlPagevisitor=newHtmlPage(myParser);

myParser.visitAllNodesWith(visitor);

StringtextInPage=visitor.getTitle();

System.out.println(textInPage);
}

/**
*按页面方式处理.对一个标准的Html页面,推荐使用此种方式.
*/
publicstaticvoidtest4(Stringcontent)throwsException
{
ParsermyParser;
myParser=Parser.createParser(content,"GBK");

HtmlPagevisitor=newHtmlPage(myParser);

myParser.visitAllNodesWith(visitor);

StringtextInPage=visitor.getTitle();

System.out.println(textInPage);
}

/**
*利用Visitor模式解析html页面.
*
*小优点:翻译了<>等符号
*缺点:好多空格,无法提取link
*
*/
publicstaticvoidtest3(Stringcontent)throwsException
{
ParsermyParser;
myParser=Parser.createParser(content,"GBK");

TextExtractingVisitorvisitor=newTextExtractingVisitor();

myParser.visitAllNodesWith(visitor);

StringtextInPage=visitor.getExtractedText();

System.out.println(textInPage);
}

/**
*得到普通文本和链接的内容.
*
*使用了过滤条件.
*/
publicstaticvoidtest2(Stringcontent)throwsParserException
{
ParsermyParser;
NodeListnodeList=null;

myParser=Parser.createParser(content,"GBK");

NodeFiltertextFilter=newNodeClassFilter(TextNode.class);
NodeFilterlinkFilter=newNodeClassFilter(LinkTag.class);

//暂时不处理meta
//NodeFiltermetaFilter=newNodeClassFilter(MetaTag.class);

OrFilterlastFilter=newOrFilter();
lastFilter.setPredicates(newNodeFilter[]{textFilter,linkFilter});

nodeList=myParser.parse(lastFilter);

Node[]nodes=nodeList.toNodeArray();

for(inti=0;i<nodes.length;i++)
{
Nodeanode=(Node)nodes[i];

Stringline="";
if(anodeinstanceofTextNode)
{
TextNodetextnode=(TextNode)anode;
//line=textnode.toPlainTextString().trim();
line=textnode.getText();
}
elseif(anodeinstanceofLinkTag)
{
LinkTaglinknode=(LinkTag)anode;

line=linknode.getLink();
//@todo("")过滤jsp标签:可以自己实现这个函数
//line=StringFunc.replace(line,"<%.*%>","");
}

if(isTrimEmpty(line))
continue;

System.out.println(line);
}
}

/**
*解析普通文本节点.
*
*@paramcontent
*@throwsParserException
*/
publicstaticvoidtest1(Stringcontent)throwsParserException
{
ParsermyParser;
Node[]nodes=null;

myParser=Parser.createParser(content,null);

nodes=myParser.extractAllNodesThatAre(TextNode.class);//exceptioncouldbethrownhere

for(inti=0;i<nodes.length;i++)
{
TextNodetextnode=(TextNode)nodes[i];
Stringline=textnode.toPlainTextString().trim();
if(line.equals(""))
continue;
System.out.println(line);
}

}

/**
*读取一个文件到字符串里.
*
*@paramsFileName文件名
*@paramsEncodeString
*@return文件内容
*/
publicstaticStringreadTextFile(StringsFileName,StringsEncode)
{
StringBuffersbStr=newStringBuffer();

try
{
Fileff=newFile(sFileName);
InputStreamReaderread=newInputStreamReader(newFileInputStream(ff),
sEncode);
BufferedReaderins=newBufferedReader(read);

StringdataLine="";
while(null!=(dataLine=ins.readLine()))
{
sbStr.append(dataLine);
sbStr.append("\r\n");
}

ins.close();
}
catch(Exceptione)
{
LogMan.error("readTextFileError",e);
}

returnsbStr.toString();
}

/**
*去掉左右空格后字符串是否为空
*@paramastrString
*@returnboolean
*/
publicstaticbooleanisTrimEmpty(Stringastr)
{
if((null==astr)||(astr.length()==0))
{
returntrue;
}
if(isBlank(astr.trim()))
{
returntrue;
}
returnfalse;
}

/**
*字符串是否为空:null或者长度为0.
*@paramastr源字符串.
*@returnboolean
*/
publicstaticbooleanisBlank(Stringastr)
{
if((null==astr)||(astr.length()==0))
{
returntrue;
}
else
{
returnfalse;
}
}

}

2.使用HttpClientHtmlParser实现简易爬虫

 本小结简单的介绍一下HttpClinetHtmlParser两个开源的项目,以及他们的网站和提供下载的地址。

  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为其提供了强大而灵活易用的开源类库,大大节省了写一个网页解析器的开销。HtmlParserhttp://sourceforge.net上活跃的一个开源项目,它提供了线性和嵌套两种方式来解析网页,主要用于html网页的转换(Transformation)以及网页内容的抽取(Extraction)HtmlParser有如下一些易于使用的特性:过滤器(Filters),访问者模式(Visitors),处理自定义标签以及易于使用的JavaBeans。正如HtmlParser首页所说:它是一个快速,健壮以及严格测试过的组件;以它设计的简洁,程序运行的速度以及处理Internet上真实网页的能力吸引着越来越多的开发者。本文中就是利用HtmlParser里提取网页里的链接,实现简易爬虫里的关键部分。HtmlParser最新的版本是HtmlParser1.6,可以登陆这里下载其源码、API参考文档以及JAR包。


 简单强大的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()方法用来对抽取的链接进行过滤。

  下面是各个类的源码,代码中的注释有比较详细的说明。

3.Htmlparser汇总说明

关键字:htmlparser

需要做一个垂直搜索引擎,比较了nekohtmlhtmlparser的功能,尽管nekohtml在容错性、性能等方面的口碑好像比htmlparser好(htmlunit也用的是nekohtml),但感觉nekohtml的测试用例和文档都比htmlparser都少,而且htmlparser基本上能够满足垂直搜索引擎页面处理分析的需求,因此先研究一下htmlparser的使用,有空再研究nekohtmlmozillahtmlparser的使用。

html的功能还是官方说得最为清楚,

引用

HTMLParserisaJavalibraryusedtoparseHTMLineitheralinearornestedfashion.Primarilyusedfortransformationorextraction,itfeaturesfilters,visitors,customtagsandeasytouseJavaBeans.Itisafast,robustandwelltestedpackage.

Thetwofundamentaluse-casesthatarehandledbytheparserareextractionandtransformation(thesynthesesuse-case,whereHTMLpagesarecreatedfromscratch,isbetterhandledbyothertoolsclosertothesourceofdata).Whilepriorversionsconcentratedondataextractionfromwebpages,Version1.4oftheHTMLParserhassubstantialimprovementsintheareaoftransformingwebpages,withsimplifiedtagcreationandediting,andverbatimtoHtml()methodoutput.



研究的重点还是extraction的使用,有空再研究transformation的使用。
1、htmlparser对html页面处理的数据结构



如图所示,HtmlParser采用了经典的Composite模式,通过RemarkNodeTextNodeTagNodeAbstractNodeTag来描述HTML页面各元素。

*org.htmlparser.Node

Node接口定义了进行树形结构节点操作的各种典型操作方法,

包括:

节点到html文本、text文本的方法:toPlainTextStringtoHtml

典型树形结构遍历的方法:getParentgetChildrengetFirstChildgetLastChildgetPreviousSiblinggetNextSiblinggetText

获取节点对应的树形结构结构的顶级节点Page对象方法:getPage

获取节点起始位置的方法:getStartPositiongetEndPosition

Visitor方法遍历节点时候方法:accept(NodeVisitorvisitor)

Filter方法:collectInto(NodeListlist,NodeFilterfilter)

Object方法:toStringclone

*org.htmlparser.nodes.AbstractNode

AbstractNode是形成HTML树形结构抽象基类,实现了Node接口。

htmlparser中,Node分成三类:

RemarkNode:代表Html中的注释

TagNode:标签节点。

TextNode:文本节点

这三类节点都继承AbstractNode

*org.htmlparser.nodes.TagNode

TagNode包含了对HTML处理的核心的各个类,是所有TAG的基类,其中有分为包含其他TAG的复合节点ComositeTag和不包含其他TAG的叶子节点Tag

复合节点CompositeTag

AppletTag,BodyTag,Bullet,BulletList,DefinitionList,DefinitionListBullet,Div,FormTag,FrameSetTag,HeadingTag,

HeadTag,Html,LabelTag,LinkTag,ObjectTag,ParagraphTag,ScriptTag,SelectTag,Span,StyleTag,TableColumn,

TableHeader,TableRow,TableTag,TextareaTag,TitleTag

叶子节点TAG

BaseHrefTag,DoctypeTag,FrameTag,ImageTag,InputTag,JspTag,MetaTag,ProcessingInstructionTag,
2htmlparserhtml页面处理的算法

主要是如下几种方式

l采用Visitor方式访问Html

1.3、htmlparser关键包结构说明

2.

3.htmlparser其实核心代码并不多,好好研究一下其代码,弥补文档不足的问题。同时htmlparser的代码注释和单元测试用例还是很齐全的,也有助于了解htmlparser的用法。

4.

5.

6.3.1、org.htmlparser

7.

8.定义了htmlparser的一些基础类。其中最为重要的是Parser类。

9.

10.Parser是htmlparser的最核心的类,其构造函数提供了如下:Parser.createParser(Stringhtml,Stringcharset)、Parser()、Parser(Lexerlexer,ParserFeedbackfb)、Parser(URLConnectionconnection,ParserFeedbackfb)、Parser(Stringresource,ParserFeedbackfeedback)、Parser(Stringresource)

11.

12.各构造函数的具体用法及含义可以查看其代码,很容易理解。

13.

14.Parser常用的几个方法:

15.

16.*elements获取元素

17.

18.Parserparser=newParser(”http://www.google.com”);

19.for(NodeIteratori=parser.elements();i.hasMoreElements();)

20.processMyNodes(i.nextNode());

21.

22.*parse(NodeFilterfilter):通过NodeFilter方式获取

23.*visitAllNodesWith(NodeVisitorvisitor):通过Nodevisitor方式

24.*extractAllNodesThatMatch(NodeFilterfilter):通过NodeFilter方式

25.

26.3.2、org.htmlparser.beans

27.

28.对Visitor和Filter的方法进行了封装,定义了针对一些常用html元素操作的bean,简化对常用元素的提取操作。

29.

30.包括:FilterBean、HTMLLinkBean、HTMLTextBean、LinkBean、StringBean、BeanyBaby等。

31.3.3、org.htmlparser.nodes

32.

33.定义了基础的node,包括:AbstractNode、RemarkNode、TagNode、TextNode等。

34.3.4、org.htmlparser.tags

35.

36.定义了htmlparser的各种tag。

37.3.5、org.htmlparser.filters

38.

39.定义了htmlparser所提供的各种filter,主要通过extractAllNodesThatMatch(NodeFilterfilter)来对html页面指定类型的元素进行过滤,包括:AndFilter、CssSelectorNodeFilter、HasAttributeFilter、HasChildFilter、HasParentFilter、HasSiblingFilter、IsEqualFilter、LinkRegexFilter、LinkStringFilter、NodeClassFilter、NotFilter、OrFilter、RegexFilter、StringFilter、TagNameFilter、XorFilter

40.3.6、org.htmlparser.visitors

41.

42.定义了htmlparser所提供的各种visitor,主要通过visitAllNodesWith(NodeVisitorvisitor)来对html页面元素进行遍历,包括:HtmlPage、LinkFindingVisitor、NodeVisitor、ObjectFindingVisitor、StringFindingVisitor、TagFindingVisitor、TextExtractingVisitor、UrlModifyingVisitor

43.

44.

45.3.7、org.htmlparser.parserapplications

46.

47.定义了一些实用的工具,包括LinkExtractor、SiteCapturer、StringExtractor、WikiCapturer,这几个类也可以作为htmlparser使用样例。

48.3.8、org.htmlparser.tests

49.

50.对各种功能的单元测试用例,也可以作为htmlparser使用的样例。

51.

52.

53.4、htmlparser的使用样例

54.

55.

56.

57.importjava.net.URL;

58.

59.importjunit.framework.TestCase;

60.

61.importorg.apache.log4j.Logger;

62.importorg.htmlparser.Node;

63.importorg.htmlparser.NodeFilter;

64.importorg.htmlparser.Parser;

65.importorg.htmlparser.Tag;

66.importorg.htmlparser.beans.LinkBean;

67.importorg.htmlparser.filters.NodeClassFilter;

68.importorg.htmlparser.filters.OrFilter;

69.importorg.htmlparser.filters.TagNameFilter;

70.importorg.htmlparser.tags.HeadTag;

71.importorg.htmlparser.tags.ImageTag;

72.importorg.htmlparser.tags.InputTag;

73.importorg.htmlparser.tags.LinkTag;

74.importorg.htmlparser.tags.OptionTag;

75.importorg.htmlparser.tags.SelectTag;

76.importorg.htmlparser.tags.TableColumn;

77.importorg.htmlparser.tags.TableRow;

78.importorg.htmlparser.tags.TableTag;

79.importorg.htmlparser.tags.TitleTag;

80.importorg.htmlparser.util.NodeIterator;

81.importorg.htmlparser.util.NodeList;

82.importorg.htmlparser.util.ParserException;

83.importorg.htmlparser.visitors.HtmlPage;

84.importorg.htmlparser.visitors.NodeVisitor;

85.importorg.htmlparser.visitors.ObjectFindingVisitor;

86.

87.publicclassParserTestCaseextendsTestCase{

88.

89.privatestaticfinalLoggerlogger=Logger.getLogger(ParserTestCase.class);

90.

91.publicParserTestCase(Stringname){

92.super(name);

93.}

94./*

95.*测试ObjectFindVisitor的用法

96.*/

97.publicvoidtestImageVisitor(){

98.try{

99.ImageTagimgLink;

100.ObjectFindingVisitorvisitor=newObjectFindingVisitor(

101.ImageTag.class);

102.Parserparser=newParser();

103.parser.setURL(”http://www.google.com”);

104.parser.setEncoding(parser.getEncoding());

105.parser.visitAllNodesWith(visitor);

106.Node[]nodes=visitor.getTags();

107.for(inti=0;i<nodes.length;i++){

108.imgLink=(ImageTag)nodes[i];

109.logger.fatal(”testImageVisitor()ImageURL=“

110.+imgLink.getImageURL());

111.logger.fatal(”testImageVisitor()ImageLocation=“

112.+imgLink.extractImageLocn());

113.logger.fatal(”testImageVisitor()SRC=“

114.+imgLink.getAttribute(”SRC”));

115.}

116.}

117.catch(Exceptione){

118.e.printStackTrace();

119.}

120.}

121./*

122.*测试TagNameFilter用法

123.*/

124.publicvoidtestNodeFilter(){

125.try{

126.NodeFilterfilter=newTagNameFilter(”IMG”);

127.Parserparser=newParser();

128.parser.setURL(”http://www.google.com”);

129.parser.setEncoding(parser.getEncoding());

130.NodeListlist=parser.extractAllNodesThatMatch(filter);

131.for(inti=0;i<list.size();i++){

132.logger.fatal(”testNodeFilter()”+list.elementAt(i).toHtml());

133.}

134.}catch(Exceptione){

135.e.printStackTrace();

136.}

137.

138.}

139./*

140.*测试NodeClassFilter用法

141.*/

142.publicvoidtestLinkTag(){

143.try{

144.

145.NodeFilterfilter=newNodeClassFilter(LinkTag.class);

146.Parserparser=newParser();

147.parser.setURL(”http://www.google.com”);

148.parser.setEncoding(parser.getEncoding());

149.NodeListlist=parser.extractAllNodesThatMatch(filter);

150.for(inti=0;i<list.size();i++){

151.LinkTagnode=(LinkTag)list.elementAt(i);

152.logger.fatal(”testLinkTag()Linkis:”+node.extractLink());

153.}

154.}catch(Exceptione){

155.e.printStackTrace();

156.}

157.

158.}

159./*

160.*测试<linkhref=”text=’text/css’rel=’stylesheet’/>用法

161.*/

162.publicvoidtestLinkCSS(){

163.try{

164.

165.Parserparser=newParser();

166.parser

167..setInputHTML(”<head><title>LinkTest</title>”

168.+“<linkhref=’/test01/css.css’text=’text/css’rel=’stylesheet’/>”

169.+“<linkhref=’/test02/css.css’text=’text/css’rel=’stylesheet’/>”

170.+“</head>”+“<body>”);

171.parser.setEncoding(parser.getEncoding());

172.NodeListnodeList=null;

173.

174.for(NodeIteratore=parser.elements();e.hasMoreNodes();){

175.Nodenode=e.nextNode();

176.logger

177..fatal(”testLinkCSS()”+node.getText()

178.+node.getClass());

179.

180.}

181.}catch(Exceptione){

182.e.printStackTrace();

183.}

184.}

185./*

186.*测试OrFilter的用法

187.*/

188.publicvoidtestOrFilter(){

189.NodeFilterinputFilter=newNodeClassFilter(InputTag.class);

190.NodeFilterselectFilter=newNodeClassFilter(SelectTag.class);

191.ParsermyParser;

192.NodeListnodeList=null;

193.

194.try{

195.Parserparser=newParser();

196.parser

197..setInputHTML(”<head><title>OrFilterTest</title>”

198.+“<linkhref=’/test01/css.css’text=’text/css’rel=’stylesheet’/>”

199.+“<linkhref=’/test02/css.css’text=’text/css’rel=’stylesheet’/>”

200.+“</head>”

201.+“<body>”

202.+“<inputtype=’text’value=’text1′name=’text1′/>”

203.+“<inputtype=’text’value=’text2′name=’text2′/>”

204.+“<select><optionid=’1′>1</option><optionid=’2′>2</option><optionid=’3′></option></select>”

205.+“<ahref=’http://www.yeeach.com’>yeeach.com</a>”

206.+“</body>”);

207.

208.parser.setEncoding(parser.getEncoding());

209.OrFilterlastFilter=newOrFilter();

210.lastFilter.setPredicates(newNodeFilter[]{selectFilter,

211.inputFilter});

212.nodeList=parser.parse(lastFilter);

213.for(inti=0;i<=nodeList.size();i++){

214.if(nodeList.elementAt(i)instanceofInputTag){

215.InputTagtag=(InputTag)nodeList.elementAt(i);

216.logger.fatal(”OrFiltertagnameis:”+tag.getTagName()

217.+”,tagvalueis:”+tag.getAttribute(”value”));

218.}

219.if(nodeList.elementAt(i)instanceofSelectTag){

220.SelectTagtag=(SelectTag)nodeList.elementAt(i);

221.NodeListlist=tag.getChildren();

222.

223.for(intj=0;j<list.size();j++){

224.OptionTagoption=(OptionTag)list.elementAt(j);

225.logger

226..fatal(”OrFilterOption”

227.+option.getOptionText());

228.}

229.

230.}

231.}

232.

233.}catch(ParserExceptione){

234.e.printStackTrace();

235.}

236.}

237./*

238.*测试对<table><tr><td></td></tr></table>的解析

239.*/

240.publicvoidtestTable(){

241.ParsermyParser;

242.NodeListnodeList=null;

243.myParser=Parser.createParser(”<body>”+“<tableid=’table1′>”

244.+“<tr><td>1-11</td><td>1-12</td><td>1-13</td>”

245.+“<tr><td>1-21</td><td>1-22</td><td>1-23</td>”

246.+“<tr><td>1-31</td><td>1-32</td><td>1-33</td></table>”

247.+“<tableid=’table2′>”

248.+“<tr><td>2-11</td><td>2-12</td><td>2-13</td>”

249.+“<tr><td>2-21</td><td>2-22</td><td>2-23</td>”

250.+“<tr><td>2-31</td><td>2-32</td><td>2-33</td></table>”

251.+“</body>”,“GBK”);

252.NodeFiltertableFilter=newNodeClassFilter(TableTag.class);

253.OrFilterlastFilter=newOrFilter();

254.lastFilter.setPredicates(newNodeFilter[]{tableFilter});

255.try{

256.nodeList=myParser.parse(lastFilter);

257.for(inti=0;i<=nodeList.size();i++){

258.if(nodeList.elementAt(i)instanceofTableTag){

259.TableTagtag=(TableTag)nodeList.elementAt(i);

260.TableRow[]rows=tag.getRows();

261.

262.for(intj=0;j<rows.length;j++){

263.TableRowtr=(TableRow)rows[j];

264.TableColumn[]td=tr.getColumns();

265.for(intk=0;k<td.length;k++){

266.logger.fatal(”<td>”+td[k].toPlainTextString());

267.}

268.

269.}

270.

271.}

272.}

273.

274.}catch(ParserExceptione){

275.e.printStackTrace();

276.}

277.}

278./*

279.*测试NodeVisitor的用法,遍历所有节点

280.*/

281.publicvoidtestVisitorAll(){

282.try{

283.Parserparser=newParser();

284.parser.setURL(”http://www.google.com”);

285.parser.setEncoding(parser.getEncoding());

286.NodeVisitorvisitor=newNodeVisitor(){

287.publicvoidvisitTag(Tagtag){

288.logger.fatal(”testVisitorAll()Tagnameis:”

289.+tag.getTagName()+”\nClassis:”

290.+tag.getClass());

291.}

292.

293.};

294.

295.parser.visitAllNodesWith(visitor);

296.}catch(ParserExceptione){

297.e.printStackTrace();

298.}

299.}

300./*

301.*测试对指定Tag的NodeVisitor的用法

302.*/

303.publicvoidtestTagVisitor(){

304.try{

305.

306.Parserparser=newParser(

307.“<head><title>dddd</title>”

308.+“<linkhref=’/test01/css.css’text=’text/css’rel=’stylesheet’/>”

309.+“<linkhref=’/test02/css.css’text=’text/css’rel=’stylesheet’/>”

310.+“</head>”+“<body>”

311.+“<ahref=’http://www.yeeach.com’>yeeach.com</a>”

312.+“</body>”);

313.NodeVisitorvisitor=newNodeVisitor(){

314.publicvoidvisitTag(Tagtag){

315.if(taginstanceofHeadTag){

316.logger.fatal(”visitTag()HeadTag:Tagnameis:”

317.+tag.getTagName()+”\nClassis:”

318.+tag.getClass()+“\nTextis:”

319.+tag.getText());

320.}elseif(taginstanceofTitleTag){

321.logger.fatal(”visitTag()TitleTag:Tagnameis:”

322.+tag.getTagName()+”\nClassis:”

323.+tag.getClass()+“\nTextis:”

324.+tag.getText());

325.

326.

327.}elseif(taginstanceofLinkTag){

328.logger.fatal(”visitTag()LinkTag:Tagnameis:”

329.+tag.getTagName()+”\nClassis:”

330.+tag.getClass()+“\nTextis:”

331.+tag.getText()+”\ngetAttributeis:”

332.+tag.getAttribute(”href”));

333.}else{

334.logger.fatal(”visitTag():Tagnameis:”

335.+tag.getTagName()+”\nClassis:”

336.+tag.getClass()+“\nTextis:”

337.+tag.getText());

338.}

339.

340.}

341.

342.};

343.

344.parser.visitAllNodesWith(visitor);

345.}catch(Exceptione){

346.e.printStackTrace();

347.}

348.}

349./*

350.*测试HtmlPage的用法

351.*/

352.publicvoidtestHtmlPage(){

353.StringinputHTML=“<html>”+“<head>”

354.+“<title>WelcometotheHTMLParserwebsite</title>”

355.+“</head>”+“<body>”+“WelcometoHTMLParser”

356.+“<tableid=’table1′>”

357.+“<tr><td>1-11</td><td>1-12</td><td>1-13</td>”

358.+“<tr><td>1-21</td><td>1-22</td><td>1-23</td>”

359.+“<tr><td>1-31</td><td>1-32</td><td>1-33</td></table>”

360.+“<tableid=’table2′>”

361.+“<tr><td>2-11</td><td>2-12</td><td>2-13</td>”

362.+“<tr><td>2-21</td><td>2-22</td><td>2-23</td>”

363.+“<tr><td>2-31</td><td>2-32</td><td>2-33</td></table>”

364.+“</body>”+“</html>”;

365.Parserparser=newParser();

366.try{

367.parser.setInputHTML(inputHTML);

368.parser.setEncoding(parser.getURL());

369.HtmlPagepage=newHtmlPage(parser);

370.parser.visitAllNodesWith(page);

371.logger.fatal(”testHtmlPage-titleis:”+page.getTitle());

372.NodeListlist=page.getBody();

373.

374.for(NodeIteratoriterator=list.elements();iterator

375..hasMoreNodes();){

376.Nodenode=iterator.nextNode();

377.logger.fatal(”testHtmlPage-nodeis:”+node.toHtml());

378.}

379.

380.}catch(ParserExceptione){

381.//TODOAuto-generatedcatchblock

382.e.printStackTrace();

383.}

384.}

385./*

386.*测试LinkBean的用法

387.*/

388.publicvoidtestLinkBean(){

389.Parserparser=newParser();

390.

391.LinkBeanlinkBean=newLinkBean();

392.linkBean.setURL(”http://www.google.com”);

393.URL[]urls=linkBean.getLinks();

394.

395.for(inti=0;i<urls.length;i++){

396.URLurl=urls[i];

397.logger.fatal(”testLinkBean()-urlis:”+url);

398.}

399.

400.}

401.

402.}

packagecn;


importjava.io.BufferedReader;

importjava.io.File;

importjava.io.FileOutputStream;

importjava.io.IOException;

importjava.io.InputStream;

importjava.io.InputStreamReader;

importjava.io.OutputStream;

importjava.net.ConnectException;

importjava.net.MalformedURLException;

importjava.net.URL;

importjava.util.ArrayList;

importjava.util.List;

importjava.util.UUID;


importorg.htmlparser.NodeFilter;

importorg.htmlparser.Parser;

importorg.htmlparser.filters.TagNameFilter;

importorg.htmlparser.tags.ImageTag;

importorg.htmlparser.util.NodeList;

importorg.htmlparser.util.ParserException;

importorg.htmlparser.visitors.HtmlPage;


publicclassgetAll{

privatefinalstaticStringCRLF=System.getProperty("line.separator");//回车换行


publicstaticvoidmakeHtm(intx){

InputStreaminstr=null;

Listlist=newArrayList<String>();

for(;x>89205;x--){

list.clear();

try{

URLur=newURL("你要扒的地址"+x+".html");//这个要按照情况而定了,我不多说了。

try{

System.out.println("正在加载页面:"+ur.toString());

instr=ur.openStream();//获得网页输出流

}catch(ConnectExceptione){

System.out.println(e.toString());

makeHtm(--x);//如果连接超时,将会抛出这个异常并且换成新的网址继续扒。

}

Strings=null;

BufferedReaderin=newBufferedReader(newInputStreamReader(

instr));

StringBuffersb=newStringBuffer();


while((s=in.readLine())!=null){

sb.append(s+CRLF);//读取网页信息,放入字符串缓冲区

}

Parserparser=Parser.createParser(sb.toString(),"utf-8");//获得整个网页的缓冲区创建解析器

HtmlPagepage=newHtmlPage(parser);//把解析器交给解析htmlpage

try{

parser.visitAllNodesWith(page);

}catch(ParserExceptione1){

e1=null;

}

NodeListnodelist=page.getBody();//获得网页的body部分

NodeFilterfilter=newTagNameFilter("IMG");//过滤img标签也可以过滤

//sapna等标签


nodelist=nodelist.extractAllNodesThatMatch(filter,true);

for(inti=0;i<nodelist.size();i++){

ImageTaglink=(ImageTag)nodelist.elementAt(i);//获得所有的

//IMG标签

Stringsrc=link.getAttribute("src");//获得img标签的src属性、这个属性就是

//就是那个图片的网址

list.add(src);

/**

*LinkTaglink=(LinkTag)nodelist.elementAt(i);//链接地址

*System.out.println(link.getAttribute("href")+"\n");//

*链接名称System.out.println(link.getStringText());

*如果过滤超链接就这样写当然上面的filter的过滤条件要改成"A"

*/

}

in.close();

down(list,x);//调用down方法交给那个存放链接的集合,和当前下载的x

list.clear();

}catch(MalformedURLExceptione){

e.printStackTrace();

}catch(IOExceptione){

e.printStackTrace();

}

}

System.out.println("下载完成");

}


publicstaticvoiddown(List<String>list,intx)throwsIOException{

Stringsubstring=UUID.randomUUID().toString();

InputStreamin=null;

try{

if(list!=null){

for(Stringsrc:list){

URLurl=newURL(src);

try{

System.out.println("正在下载:"+url.toString());

in=url.openStream();

}catch(ConnectExceptione){

System.out.println(e.toString());

list.clear();

makeHtm(--x);

}

Stringstring=UUID.randomUUID().toString();

Fileforder=newFile("F://fuck//"+substring);

if(!forder.exists()){

forder.mkdir();

}

Filefile=newFile("F://xx//"+substring+"//"+string

+".jpg");//每个网页的图片都放在一个UUID的文件夹里,每个图片都是

//一个UUID的名字

OutputStreamout=newFileOutputStream(file);

byte[]b=newbyte[1024*6];//我习惯这个数字你可以改大点

intlen;

while((len=in.read(b))!=-1){

out.write(b,0,len);//流的对拷,不多说了

out.flush();

}

}

}

}catch(MalformedURLExceptione){

makeHtm(--x);

e.printStackTrace();

}

}

}

当然你别忘记写个main方法调用他

共同学习,共同进步。

我的博客http://avjv.blog.163.com/邮箱[email protected]

你可能感兴趣的:(HtmlParser)