输出结果: getText:!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" getPlainText: toHtml: toHtml(true): toHtml(false): toString:Doctype Tag : !DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd; begins at : 0; ends at : 121 ================================================= getText:
getPlainText:
toHtml:
toHtml(true):
toHtml(false):
toString:Txt (121[0,121],123[1,0]): \n ================================================= getText:head getPlainText:白泽居-www.baizeju.com toHtml:白泽居-www.baizeju.com toHtml(true):白泽居-www.baizeju.com toHtml(false):白泽居-www.baizeju.com toString:HEAD: Tag (123[1,0],129[1,6]): head Tag (129[1,6],197[1,74]): meta http-equiv="Content-Type" content="text/html; ... Tag (197[1,74],204[1,81]): title Txt (204[1,81],223[1,100]): 白泽居-www.baizeju.com End (223[1,100],231[1,108]): /title End (231[1,108],238[1,115]): /head
toString:Tag (240[2,0],283[2,43]): html xmlns="http://www.w3.org/1999/xhtml" Txt (283[2,43],285[3,0]): \n Tag (285[3,0],292[3,7]): body Txt (292[3,7],294[4,0]): \n Tag (294[4,0],313[4,19]): div id="top_main" Txt (313[4,19],316[5,1]): \n\t Tag (316[5,1],336[5,21]): div id="logoindex" Txt (336[5,21],340[6,2]): \n\t\t Rem (340[6,2],351[6,13]): 这是注释 Txt (351[6,13],376[8,0]): \n\t\t白泽居-www.baizeju.com\n Tag (376[8,0],409[8,33]): a href="http://www.baizeju.com" Txt (409[8,33],428[8,52]): 白泽居-www.baizeju.com End (428[8,52],432[8,56]): /a Txt (432[8,56],435[9,1]): \n\t End (435[9,1],441[9,7]): /div Txt (441[9,7],465[11,0]): \n\t白泽居-www.baizeju.com\n End (465[11,0],471[11,6]): /div Txt (471[11,6],473[12,0]): \n End (473[12,0],480[12,7]): /body Txt (480[12,7],482[13,0]): \n End (482[13,0],489[13,7]): /html
Parser parser = new Parser( (HttpURLConnection) (new URL("http://127.0.0.1:8080/HTMLParserTester.html")).openConnection() );
NodeVisitor visitor = new NodeVisitor( false, false ) {
publicvoid visitTag(Tag tag) {
message("This is Tag:"+tag.getText());
}
publicvoid visitStringNode (Text string) {
message("This is Text:"+string);
}
publicvoid visitRemarkNode (Remark remark) {
message("This is Remark:"+remark.getText());
}
publicvoid beginParsing () {
message("beginParsing");
}
publicvoid visitEndTag (Tag tag){
message("visitEndTag:"+tag.getText());
}
publicvoid finishedParsing () {
message("finishedParsing");
}
};
parser.visitAllNodesWith(visitor);
}
catch( Exception e ) {
e.printStackTrace();
}
}
输出结果: beginParsing This is Tag:!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" This is Text:Txt (121[0,121],123[1,0]): \n This is Text:Txt (244[1,121],246[2,0]): \n finishedParsing
我们先把recurseSelf设置成true,看看会发生什么。 NodeVisitor visitor = new NodeVisitor( false, true) { 输出结果: beginParsing This is Tag:!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" This is Text:Txt (121[0,121],123[1,0]): \n This is Tag:head This is Text:Txt (244[1,121],246[2,0]): \n This is Tag:html xmlns="http://www.w3.org/1999/xhtml" finishedParsing 可以看到,HTML页面的第一层节点都被调用了。
我们再用下面的方法调用看看: NodeVisitor visitor = new NodeVisitor( true, false) { 输出结果: beginParsing This is Tag:!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" This is Text:Txt (121[0,121],123[1,0]): \n This is Tag:meta http-equiv="Content-Type" content="text/html; charset=gb2312" This is Text:Txt (204[1,81],229[1,106]): 白泽居-title-www.baizeju.com visitEndTag:/title visitEndTag:/head This is Text:Txt (244[1,121],246[2,0]): \n This is Text:Txt (289[2,43],291[3,0]): \n This is Text:Txt (298[3,7],300[4,0]): \n This is Text:Txt (319[4,19],322[5,1]): \n\t This is Text:Txt (342[5,21],346[6,2]): \n\t\t This is Remark:这是注释 白泽居-www.baizeju.com This is Text:Txt (378[6,34],408[8,0]): \n\t\t白泽居-字符串1-www.baizeju.com\n This is Text:Txt (441[8,33],465[8,57]): 白泽居-链接文本-www.baizeju.com visitEndTag:/a This is Text:Txt (469[8,61],472[9,1]): \n\t visitEndTag:/div This is Text:Txt (478[9,7],507[11,0]): \n\t白泽居-字符串2-www.baizeju.com\n visitEndTag:/div This is Text:Txt (513[11,6],515[12,0]): \n visitEndTag:/body This is Text:Txt (522[12,7],524[13,0]): \n visitEndTag:/html finishedParsing 可以看到,所有的子节点都出现了,除了刚刚例子里面的两个最上层节点This is Tag:head和This is Tag:html xmlns="http://www.w3.org/1999/xhtml"。 想让它们都出来,只需要 NodeVisitor visitor = new NodeVisitor( true, true) { 输出结果: beginParsing This is Tag:!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" This is Text:Txt (121[0,121],123[1,0]): \n This is Tag:head This is Tag:meta http-equiv="Content-Type" content="text/html; charset=gb2312" This is Tag:title This is Text:Txt (204[1,81],229[1,106]): 白泽居-title-www.baizeju.com visitEndTag:/title visitEndTag:/head This is Text:Txt (244[1,121],246[2,0]): \n This is Tag:html xmlns="http://www.w3.org/1999/xhtml" This is Text:Txt (289[2,43],291[3,0]): \n This is Tag:body This is Text:Txt (298[3,7],300[4,0]): \n This is Tag:div id="top_main" This is Text:Txt (319[4,19],322[5,1]): \n\t This is Tag:div id="logoindex" This is Text:Txt (342[5,21],346[6,2]): \n\t\t This is Remark:这是注释 白泽居-www.baizeju.com This is Text:Txt (378[6,34],408[8,0]): \n\t\t白泽居-字符串1-www.baizeju.com\n This is Tag:a href="http://www.baizeju.com" This is Text:Txt (441[8,33],465[8,57]): 白泽居-链接文本-www.baizeju.com visitEndTag:/a This is Text:Txt (469[8,61],472[9,1]): \n\t visitEndTag:/div This is Text:Txt (478[9,7],507[11,0]): \n\t白泽居-字符串2-www.baizeju.com\n visitEndTag:/div This is Text:Txt (513[11,6],515[12,0]): \n visitEndTag:/body This is Text:Txt (522[12,7],524[13,0]): \n visitEndTag:/html finishedParsing 哈哈,这下调用清楚了,大家在需要处理的地方增加自己的代码好了。
4.2 其他Visitor HTMLParser还定义了几个其他的Visitor。HtmlPage,NodeVisitor,ObjectFindingVisitor,StringFindingVisitor,TagFindingVisitor,TextExtractingVisitor,UrlModifyingVisitor,它们都是NodeVisitor的子类,实现了一些特定的功能。笔者个人的感觉是没什么用处,如果你需要什么特定的功能,还不如自己写一个,想在这些里面找到适合你需要的,化的时间可能更多。反正大家看看代码就发现,它们每个都没几行真正有效的代码。HTMLParser 是一个用来解析 HTML 文档的开放源码项目,它具有小巧、快速、使用简单的特点以及拥有强大的功能。对该项目还不了解的朋友可以参照 2004 年三月份我发表的文章--《 从
HTML中攫取你所需的信息
》,这篇文章介绍如何通过HTMLParser 来提取 HTML 文档中的文本数据以及提取出文档中的所有链接或者是图片等信息。
现在该项目的最新版本是 Integration Build 1.6,与之前版本的差别在于代码结构的调整、当然也有一些功能的提升以及 BugFix,同时对字符集的处理也更加自动了。比较遗憾的该项目并没有详尽的使用文档,你只能借助于它的 API 文档、一两个简单例子以及源码来熟悉它。
如果是 HTML 文档,那么用 HTMLParser 已经差不多可以满足你至少 90% 的需求。一个 HTML 文档中可能出现的标签差不多在 HTMLParser 中都有对应的类,甚至包括一些动态的脚本标签,例如 <%...%> 这种 JSP 和 ASP用到的标签都有相应的 JspTag 对应。HTMLParser 的强大功能还体现在你可以修改每个标签的属性或者它所包含的文本内容并生成新的 HTML 文档,比如你可以文档中的链接地址偷偷的改成你自己的地址等等。关于HTMLParser 的强大功能,其实上一篇文章已经介绍很多,这里不再累赘,我们今天要讲的是另外一个用途--处理自定义标签。
首先我们先解释一下什么叫自定义标签,我把所有不是 HTML 脚本语言中定义的标签称之为自定义标签,比如可以是 、 等等,这是我们自己创造出来的标签。你可能会很奇怪,因为这些标签一旦用在HTML 文档中是没有任何效果的,那么我们换另外一个例子,假如你要解析的不是 HTML 文档,而是一个WML(Wireless Markup Lauguage)文档呢?WML 文档中的 card,anchor 等标签 HTMLParser 是没有现成的标签类来处理的。还有就是你同样可以用 HTMLParser 来处理 XML 文档,而 XML 文档中所有的标签都是你自己定义的。
为了使我们的例子更具有代表意义,接下来我们将给出一段代码用来解析出 WML 文档中的所有链接,了解WML 文档的人都知道,WML 文档中除了与 HTML 文档相同的链接写法外,还多了一种标签叫 ,例如在一个 WML 文档我们可以用下面两种方式来表示一个链接。
Mark Roberge是HubSpot的首席财务官,在招聘销售职位时使用了大量数据分析。但是科技并没有挤走直觉。
大家都知道数理学家实际上已经渗透到了各行各业。这些热衷数据的人们通过处理数据理解商业流程的各个方面,以重组弱点,增强优势。
Mark Roberge是美国HubSpot公司的首席财务官,HubSpot公司在构架集客营销现象方面出过一份力——因此他也是一位数理学家。他使用数据分析
@echo off
: host=服务器证书域名或ip,需要和部署时服务器的域名或ip一致 ou=公司名称, o=公司名称
set host=localhost
set ou=localhost
set o=localhost
set password=123456
set validity=3650
set salias=s