原文:
HTMLParser简单应用
NanShan 跟大家研究一下HTMLParser简单应用,HTMLParser遍历了网页的内容以后,以树(森林)结构保存了结果。HTMLParser访问结果内容的方法有两种。使用Filter和使用Visitor 常用的filter(用来作为解析过滤条件)判断类Filter:TagNameFilter、HasAttributeFilter、HasChildFilter、HasParentFilter、HasSiblingFilter、IsEqualFilter 逻辑运算Filter:AndFilter、NotFilter、OrFilter、XorFilter 其他Filter:NodeClassFilter、StringFilter、LinkStringFilter、LinkRegexFilter、RegexFilter、CssSelectorNodeFilter 系统Visitor功能简介: ObjectFindingVisitor:用来找出所有指定类型的节点,采用getTags()来获取结果。 StringBean:用来从一个指定的URL获取移除了<SCRIPT></SCRIPT>和<PRE></PRE>之间代码的Html代码,也可以用做Visitor,用来移除这两种标签内部的代码,采用StringBean.getStrings()来获取结果。 HtmlPage:提取Title,body中的节点和页面中的TableTag节点。 LinkFindingVisitor:找出节点中包含某个链接的总个数。 StringFindingVisitor:找出遍历的TextNode中含有指定字符串的个数。 TagFindingVisitor:找出指定Tag的所有节点,可以指定多种类型。 TextExtractingVisitor:从网页中把所有标签去掉来提取文本,这个提取文本的Visitor有时是很实用的,只是注意在提取文本时将标签的属性也去掉了,也就是说只剩下标签之间的文本,例如<a>中的链接也去掉了。 UrlModifyingVisitor:用来修改网页中的链接。 Visitor方式访问Html: 1,整体解析过程 用一个URL或页面String做一个Parser 用这个Parser做一个Visitor 使用Parser.visitAllNodeWith(Visitor)来遍历节点 获取Visitor遍历后得到的数据 2,Visit过程 做解析之前做的事情:visitor.beginParsing(); 每次取到一个节点Node,让该Node接受accept该Visitor 做解析后做的事情:visitor.finishedParsing(); 3,获取节点的过程:逐步遍历Html,分析出Node。此部分较为复杂,且对于我们应用来说无需很多了解,暂跳过。 4,节点访问 节点访问采用Visitor模式,Node的accept方法和具体Visitor的visit方法是关键。 首先三类Node来accept的方式各不相同: 对于所有TagNode都使用一个accept方法,即TagNode的accept方法。首先判断是否是标签结尾,如果是就visitor.visitEndTag (this);否则visitor.visitTag (this); 如果是TextNode,那就visitor.visitStringNode (this);就可以了。 如果是RemarkNode,那就visitor.visitRemarkNode (this);就可以了。 实际上NodeVisitor里边这四种visit方法都是空的,因为在不同的Visitor中对于这三类节点的处理是不同的;对于需要处理的节点,只要重载对应的visit方法就行了,如果不处理那就不理会就可以了;另外,如果用户用自己的Visitor,那么还可以灵活的处理不同类型的节点了。 系统为我们实现了下面我要介绍的8种Visitor,实际上可以看作是系统给我们演示了如何做各种各样的Visitor来访问Html,因为实际上我们要真正来用HtmlParser的话,还需要特定的Visitor,而通过简单的这些系统提供的Visitor组合是难以做成什么事情的。 如果说visitor是遍历提取信息,当然这个信息可以包括某些节点或者从节点分析出来的更有效的信息,这都取决于我们的Visitor做成什么样子,那么Filter则目标很明确。Filter的调用是同Visitor独立的,因为也无需先filter出一些NodeList,再用Visitor来访问,另外,在Filter后得到NodeList以后,我们仍然可以使用NodeList的extractAllNodesThatMatch(someFilter)来进一步过滤,同时又可以用NodeList的isitAllNodesWith(someVisitor)来做进一步的访问。 这样,我们可以看到HtmlParser为我们提供了非常方便的Html解析方式,针对不同的应用可以采用visitor来遍历Html节点提取数据,也可以用Filter来过滤节点,提取出我们所关注的节点,再对节点进行处理。通过这样的组合,一定能够找出我们所需要的信息。 代码示例: static void testGetText(String context){ try { Parser parser; parser = new Parser(); //解析uri目标内容 // parser.setURL(”http://www.google.com”); //解析制定字符集的html字符串 // parser = Parser.createParser(result, "utf8"); //使用逻辑filter OrFilter一次提取多种tag // NodeFilter textFilter = new NodeClassFilter(TextNode.class); // NodeFilter linkFilter = new NodeClassFilter(LinkTag.class); // Lexer lexer = new Lexer();//使用lexer // Page page = new Page(html, encoding); // lexer.setPage(page); // parser.setLexer(lexer); // //暂时不处理 meta // //NodeFilter metaFilter = new NodeClassFilter(MetaTag.class); // OrFilter lastFilter = new OrFilter(); // lastFilter.setPredicates(new NodeFilter[] { textFilter, linkFilter }); NodeFilter filter = new NodeClassFilter( Div.class ); parser.setURL("test.html");//解析指定文件 parser.setEncoding("GBK"); NodeFilter linkFilter = new NodeClassFilter(LinkTag.class); NodeList nodelist = parser.parse(linkFilter); Node[] nodes = nodelist.toNodeArray(); String line = ""; for (int i = 0; i < nodes.length; i++) { Node node = nodes; if (node instanceof TextNode) { TextNode textnode = (TextNode) node; line = textnode.getText(); } else if (node instanceof LinkTag) { LinkTag link = (LinkTag) node; line = link.getStringText(); String test = link.getLinkText(); SimpleNodeIterator itr = link.children(); boolean hasImg = false; while(itr.hasMoreNodes()){//超链接内有img内容,取节点src元素 Node n = itr.nextNode(); if (n instanceof ImageTag) { ImageTag titlenode = (ImageTag) n; String t = titlenode.getImageURL(); System.out.println("text::::::::::"+t); titlenode.setImageURL("test"); hasImg=true; } } if(! hasImg) System.out.println("text::::::::::"+test); } else if (node instanceof TitleTag) { TitleTag titlenode = (TitleTag) node; line = titlenode.getTitle(); }else if (node instanceof ImageTag) { ImageTag titlenode = (ImageTag) node; line = titlenode.getImageURL(); } } System.out.println( nodelist.toHtml()); } catch (ParserException e) { // TODO Auto-generated catch block e.printStackTrace(); } } |