初识HtmlParser

1、概念

网页解析,即程序自动分析网页内容、获取信息,从而进一步处理信息。

htmlparser包提供方便、简洁的处理html文件的方法,它将html页面中的标签按树形结构解析成一个一个结点,一种类型的结点对应一个类,通过调用其方法可以轻松地访问标签中的内容。

(

官方文档:http://htmlparser.sourceforge.net/samples.html

API:http://htmlparser.sourceforge.net/javadoc/index.html

其它HTML 解释器:jsoup等。由于HtmlParser自2006年以后就再没更新,目前很多人推荐使用jsoup代替它。

)


2、使用HtmlPaser的关键步骤

1.用被提取的网页的url实例化一个Parser

2.实例化Filter,设置页面过滤条件——只获取<a>标签与<frame>标签的内容

3.用Parser提取页面中所有通过Filter的结点,得到NodeList

4.遍历NodeList,调用Node的相应方法得到其中的链接,加入子链接的集合

5.返回子链接集合


3、使用Parser的构造函数创建解释器

Parser() 
          Zero argument constructor.
Parser(Lexer lexer) 
          Construct a parser using the provided lexer.
Parser(Lexer lexer, ParserFeedback fb) 
          Construct a parser using the provided lexer and feedback object.
Parser(String resource) 
          Creates a Parser object with the location of the resource (URL or file).
Parser(String resource, ParserFeedback feedback) 
          Creates a Parser object with the location of the resource (URL or file) You would typically create a DefaultHTMLParserFeedback object and pass it in.
Parser(URLConnection connection) 
          Construct a parser using the provided URLConnection.
Parser(URLConnection connection, ParserFeedback fb) 
          Constructor for custom HTTP access.
    


  对于大多数使用者来说,使用最多的是通过一个URLConnection或者一个保存有网页内容的字符串来初始化Parser,或者使用静态函数来生成一个Parser对象。


4、HtmlPaser使用Node对象保存各节点信息

AbstractNodes是Node的直接子类,也是一个抽象类。它的三个直接子类实现是RemarkNode,用于保存注释。在输出结果的toString部分中可以看到有一个"Rem (345[6,2],356[6,13]): 这是注释",就是一个RemarkNode。TextNode也很简单,就是用户可见的文字信息。TagNode是最复杂的,包含了HTML语言中的所有标签,而且可以扩展(扩展 HTMLParser 对自定义标签的处理能力)。TagNode包含两类,一类是简单的Tag,实际就是不能包含其他Tag的标签,只能做叶子节点。另一类是CompositeTag,就是可以包含其他Tag,是分支节点

HTMLParser遍历了网页的内容以后,以树(森林)结构保存了结果。HTMLParser访问结果内容的方法有两种。使用Filter和使用Visitor。


(1)访问各个节点的方法
Node getParent ():取得父节点
NodeList getChildren ():取得子节点的列表
Node getFirstChild ():取得第一个子节点
Node getLastChild ():取得最后一个子节点
Node getPreviousSibling ():取得前一个兄弟(不好意思,英文是兄弟姐妹,直译太麻烦而且不符合习惯,对不起女同胞了)
Node getNextSibling ():取得下一个兄弟节点
(2)取得Node内容的函数
String getText ():取得文本
String toPlainTextString():取得纯文本信息。
String toHtml () :取得HTML信息(原始HTML
String toHtml (boolean verbatim):取得HTML信息(原始HTML
String toString ():取得字符串信息(原始HTML
Page getPage ():取得这个Node对应的Page对象
int getStartPosition ():取得这个NodeHTML页面中的起始位置
int getEndPosition ():取得这个NodeHTML页面中的结束位置

用于Filter过滤的函数:
void 
collectInto (NodeList list, NodeFilter filter)基于filter的条件对于这个节点进行过滤,符合条件的节点放到list中。
用于Visitor遍历的函数:
void 
accept (NodeVisitor visitor)对这个Node应用visitor

5、使用Filter访问Node节点及其内容

(1)Filter的种类

顾名思义,Filter就是对于结果进行过滤,取得需要的内容。

所有的Filter均实现了NodeFilter接口,此接口只有一个方法Boolean accept(Node node),用于确定某个节点是否属于此Filter过滤的范围。

HTMLParser在org.htmlparser.filters包之内一共定义了16个不同的Filter,也可以分为几类。
判断类Filter
TagNameFilter
HasAttributeFilter

HasChildFilter
HasParentFilter
HasSiblingFilter
IsEqualFilter
逻辑运算Filter
AndFilter
NotFilter

OrFilter
XorFilter
其他Filter
NodeClassFilter
StringFilter

LinkStringFilter
LinkRegexFilter
RegexFilter
CssSelectorNodeFilter

除此以外,可以自定义一些Filter,用于完成特殊需求的过滤。
(2)Filter的使用示例

以下示例用于提取HTML文件中的链接

public class HtmlNodeParser {
    
    //  http://www.sohu.com
    
    /**
     * 解析url地址中对应的页面中的    a标签与frame标签
     * 过滤器为空表示全网爬
     * @throws ParserException
     * @throws IOException
     */
    public Set<String> parseLink(   String url, NodeFilter filter) throws ParserException, IOException{
        if(    url.startsWith("http://")==false){
            url="http://"+ url;
        }
        Set<String> set=new HashSet<String>();
        
//        if(   url.lastIndexOf("?")>-1){
//            url=url+"&";
//        }else{
//            url=url+"?";
//        }
//        url=url+"zy="+UUID.randomUUID().toString().substring(0,4);
        
        URL u=new URL(   url );
        HttpURLConnection con=(HttpURLConnection) u.openConnection();
        con.setRequestProperty("Host", "download.csdn.net");
        con.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 5.1; rv:27.0) Gecko/20100101 Firefox/27.0");
        con.setRequestProperty("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
        con.connect();
        
        String rm=con.getContentType();
        //构造一个Parser,并设置相关的属性  
        Parser parser=new Parser(   con );
        String encoding= "utf-8";
        if(   rm.indexOf("charset")==-1){
            parser.setEncoding(  encoding  );
        }
        
        
        //自定义一个Filter,专门用于过滤frame标记,然后取得标签中的src属性值  
        NodeFilter framefilter=new NodeFilter(){
            @Override
            public boolean accept(Node node) {
                if(   node.getText().indexOf("frame src=")>=0  ){
                    return true;
                }else{
                    return false;
                }
            }
        };
        //  创建第二个Filter,过滤<a>标签  LinkTag表示超链接的标记,
        OrFilter linkFilter=new OrFilter(  new NodeClassFilter(LinkTag.class), framefilter );
        NodeList list = parser.extractAllNodesThatMatch (linkFilter);
        //4、对取得的Node进行处理
        for(int i=0;i<list.size();i++){
            Node node=list.elementAt(i);
            String linkurl=null;
              //如果链接类型为<a />  
            if(   node instanceof LinkTag ){          //   href
                LinkTag linkTag=(LinkTag) node;
                linkurl=linkTag.getLink();
            }else {
                //是frame节点     src    frame src=xxxx.html width=
                String frame=node.getText();
                int start=frame.indexOf("src=");                frame=frame.substring(  start );
                int end= frame.indexOf(" ");
                if(   end==-1){
                    end=frame.indexOf(">");
                }
                linkurl=frame.substring(4, end);
            }
            if(  linkurl==null  ||   "".equals(   linkurl) ||   !linkurl.startsWith("http://") ){
                continue;
            }
            //accept(  node)==>判断是否属于本次搜索范围的url
            if(   filter!=null &&   filter.accept(  node)==false ){
                continue;
            }
            //System.out.println( "========>"+ node+"\t\t   XXXXX:=> "+  linkurl  );
            set.add(    linkurl );
        }
        return set;
    }  


   

程序中的一些说明:

(1)通过Node#getText()取得节点的String。

(2)node instanceof TagLink,即<a/>节点,其它还有很多的类似节点,如tableTag等,基本上每个常见的html标签均会对应一个tag。官方文档说明如下:

org.htmlparser.nodesThe nodes package has the concrete node implementations.
org.htmlparser.tagsThe tags package contains specific tags.
因此可以通过此方法直接判断一个节点是否某个标签内容。


其中用到的LinkFilter接口定义如下:

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. package org.ljh.search.html;  
  2.   
  3. //本接口所定义的过滤器,用于判断url是否属于本次搜索范围。  
  4. public interface LinkFilter {  
  5.     public boolean accept(String url);  
  6. }  


测试程序如下:

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. package org.ljh.search.html;  
  2.   
  3. import java.util.Iterator;  
  4. import java.util.Set;  
  5.   
  6. import org.junit.Test;  
  7.   
  8. public class HtmlParserToolTest {  
  9.   
  10.     @Test  
  11.     public void testExtractLinks() {  
  12.         String url = "http://www.baidu.com";  
  13.         LinkFilter linkFilter = new LinkFilter(){  
  14.             @Override  
  15.             public boolean accept(String url) {  
  16.                 if(url.contains("baidu")){  
  17.                     return true;  
  18.                 }else{  
  19.                     return false;  
  20.                 }  
  21.             }  
  22.               
  23.         };  
  24.         Set<String> urlSet = HtmlParserTool.extractLinks(url, linkFilter);  
  25.           
  26.         Iterator<String> it = urlSet.iterator();  
  27.         while(it.hasNext()){  
  28.             System.out.println(it.next());  
  29.         }  
  30.     }  
  31.   
  32. }  


输出结果如下:

http://www.hao123.com
http://www.baidu.com/
http://www.baidu.com/duty/
http://v.baidu.com/v?ct=301989888&rn=20&pn=0&db=0&s=25&word=
http://music.baidu.com
http://ir.baidu.com
http://www.baidu.com/gaoji/preferences.html
http://news.baidu.com
http://map.baidu.com
http://music.baidu.com/search?fr=ps&key=
http://image.baidu.com
http://zhidao.baidu.com
http://image.baidu.com/i?tn=baiduimage&ct=201326592&lm=-1&cl=2&nc=1&word=
http://www.baidu.com/more/
http://shouji.baidu.com/baidusearch/mobisearch.html?ref=pcjg&from=1000139w
http://wenku.baidu.com
http://news.baidu.com/ns?cl=2&rn=20&tn=news&word=
https://passport.baidu.com/v2/?login&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2F
http://www.baidu.com/cache/sethelp/index.html
http://zhidao.baidu.com/q?ct=17&pn=0&tn=ikaslist&rn=10&word=&fr=wwwt
http://tieba.baidu.com/f?kw=&fr=wwwt
http://home.baidu.com
https://passport.baidu.com/v2/?reg&regType=1&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2F
http://v.baidu.com
http://e.baidu.com/?refer=888
;
http://tieba.baidu.com
http://baike.baidu.com
http://wenku.baidu.com/search?word=&lm=0&od=0
http://top.baidu.com

http://map.baidu.com/m?word=&fr=ps01000




六 visitor

HTMLParser遍历了网页的内容以后,以树(森林)结构保存了结果。HTMLParser访问结果内容的方法有两种。使用Filter和使用Visitor
下面介绍使用Visitor访问内容的方法。
(下面是我在网上找的例子  先存起来 以后用再来看)
NodeVisitor
从简单方面的理解,Filter是根据某种条件过滤取出需要的Node再进行处理。Visitor则是遍历内容树的每一个节点,对于符合条件的节点进行处理。实际的结果异曲同工,两种不同的方法可以达到相同的结果。
下面是一个最常见的NodeVisitro的例子。
测试代码:
   

public static void main(String[] args) {
        try{
            Parser parser = new Parser( (HttpURLConnection) (new URL("http://127.0.0.1:8080/HTMLParserTester.html")).openConnection() );

            NodeVisitor visitor = new NodeVisitor( false, false ) {
                public void visitTag(Tag tag) {
                   message("This is Tag:"+tag.getText());
                }
                public void visitStringNode (Text string)    {
                     message("This is Text:"+string);
                }
                public void visitRemarkNode (Remark remark) {
                     message("This is Remark:"+remark.getText());
                }
                public void beginParsing () {
                    message("beginParsing");
                }
                public void visitEndTag (Tag tag){
                    message("visitEndTag:"+tag.getText());
                }
                public void 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

可以看到,开始遍历所以的节点以前, beginParsing 先被调用,然后处理的是中间的 Node ,最后在结束遍历以前, finishParsing 被调用。因为我设置的  recurseChildren recurseSelf 都是 false ,所以 Visitor 没有访问子节点也没有访问根节点的内容。中间输出的两个 \n 就是我们在 HTMLParser使用详解(1初始化Parser  中讨论过的最高层的那两个换行。

我们先把 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
哈哈,这下调用清楚了,大家在需要处理的地方增加自己的代码好了。


 
其他Visitor

HTMLParser
还定义了几个其他的 Visitor HtmlPage NodeVisitor ObjectFindingVisitor StringFindingVisitor TagFindingVisitor TextExtractingVisitor UrlModifyingVisitor ,它们都是 NodeVisitor 的子类,实现了一些特定的功能。听别人说感觉是没什么用处,如果你需要什么特定的功能,还不如自己写一个,



org.htmlparser.Tag org.htmlparser.Node org.htmlparser.Text org.htmlparser.Parser org.htmlparser.Remark org.htmlparser.tags.Div org.htmlparser.Attribute org.htmlparser.tags.Html org.htmlparser.tags.Span org.htmlparser.NodeFilter org.htmlparser.lexer.Page org.htmlparser.NodeFactory org.htmlparser.http.Cookie org.htmlparser.lexer.Lexer org.htmlparser.sax.Locator org.htmlparser.tags.Bullet org.htmlparser.tags.JspTag org.htmlparser.lexer.Cursor org.htmlparser.lexer.Source org.htmlparser.lexer.Stream org.htmlparser.sax.Feedback org.htmlparser.tags.BodyTag org.htmlparser.tags.FormTag org.htmlparser.tags.HeadTag org.htmlparser.tags.LinkTag org.htmlparser.tags.MetaTag org.htmlparser.nodes.TagNode org.htmlparser.sax.XMLReader org.htmlparser.tags.FrameTag org.htmlparser.tags.ImageTag org.htmlparser.tags.InputTag org.htmlparser.tags.LabelTag org.htmlparser.tags.StyleTag org.htmlparser.tags.TableRow org.htmlparser.tags.TableTag org.htmlparser.tags.TitleTag org.htmlparser.util.NodeList org.htmlparser.beans.LinkBean org.htmlparser.nodes.TextNode org.htmlparser.sax.Attributes org.htmlparser.tags.AppletTag org.htmlparser.tags.ObjectTag org.htmlparser.tags.OptionTag org.htmlparser.tags.ScriptTag org.htmlparser.tags.SelectTag org.htmlparser.util.Translate org.htmlparser.util.sort.Sort org.htmlparser.beans.BeanyBaby org.htmlparser.http.HttpHeader org.htmlparser.lexer.PageIndex org.htmlparser.tags.BulletList org.htmlparser.tags.DoctypeTag org.htmlparser.tags.HeadingTag org.htmlparser.util.NodeList$1 org.htmlparser.beans.FilterBean org.htmlparser.beans.StringBean org.htmlparser.filters.OrFilter org.htmlparser.nodes.RemarkNode org.htmlparser.scanners.Scanner org.htmlparser.tags.BaseHrefTag org.htmlparser.tags.FrameSetTag org.htmlparser.tags.TableColumn org.htmlparser.tags.TableHeader org.htmlparser.tags.TextareaTag org.htmlparser.util.ParserUtils org.htmlparser.beans.BeanyBaby$1 org.htmlparser.filters.AndFilter org.htmlparser.filters.NotFilter org.htmlparser.filters.XorFilter org.htmlparser.tags.CompositeTag org.htmlparser.tags.ParagraphTag org.htmlparser.util.IteratorImpl org.htmlparser.util.NodeIterator org.htmlparser.visitors.HtmlPage org.htmlparser.util.sort.Ordered org.htmlparser.beans.HTMLLinkBean org.htmlparser.beans.HTMLTextBean org.htmlparser.lexer.StringSource org.htmlparser.nodes.AbstractNode org.htmlparser.util.sort.Sortable org.htmlparser.filters.RegexFilter org.htmlparser.lexer.PageAttribute org.htmlparser.scanners.JspScanner org.htmlparser.scanners.TagScanner org.htmlparser.tags.DefinitionList org.htmlparser.util.NodeTreeWalker org.htmlparser.util.ParserFeedback org.htmlparser.filters.StringFilter org.htmlparser.util.FeedbackManager org.htmlparser.util.ParserException org.htmlparser.visitors.NodeVisitor org.htmlparser.filters.IsEqualFilter org.htmlparser.filters.TagNameFilter org.htmlparser.scanners.StyleScanner org.htmlparser.util.ChainedException org.htmlparser.filters.HasChildFilter org.htmlparser.http.ConnectionManager org.htmlparser.http.ConnectionMonitor org.htmlparser.scanners.ScriptDecoder org.htmlparser.scanners.ScriptScanner org.htmlparser.PrototypicalNodeFactory org.htmlparser.filters.HasParentFilter org.htmlparser.filters.LinkRegexFilter org.htmlparser.filters.NodeClassFilter org.htmlparser.lexer.InputStreamSource org.htmlparser.util.CharacterReference org.htmlparser.util.SimpleNodeIterator org.htmlparser.filters.HasSiblingFilter org.htmlparser.filters.LinkStringFilter org.htmlparser.tags.DefinitionListBullet org.htmlparser.util.CharacterReferenceEx org.htmlparser.filters.HasAttributeFilter org.htmlparser.util.DefaultParserFeedback org.htmlparser.visitors.TagFindingVisitor org.htmlparser.visitors.LinkFindingVisitor org.htmlparser.scanners.CompositeTagScanner org.htmlparser.util.EncodingChangeException org.htmlparser.visitors.UrlModifyingVisitor org.htmlparser.filters.CssSelectorNodeFilter org.htmlparser.tags.ProcessingInstructionTag org.htmlparser.visitors.ObjectFindingVisitor org.htmlparser.visitors.StringFindingVisitor org.htmlparser.visitors.TextExtractingVisitor org.htmlparser.filters.CssSelectorNodeFilter$1 org.htmlparser.parserapplications.SiteCapturer org.htmlparser.parserapplications.WikiCapturer org.htmlparser.parserapplications.LinkExtractor org.htmlparser.parserapplications.LinkExtractor$1 org.htmlparser.parserapplications.StringExtractor org.htmlparser.filters.CssSelectorNodeFilter$YesFilter org.htmlparser.parserapplications.filterbuilder.Filter org.htmlparser.filters.CssSelectorNodeFilter$AdjacentFilter org.htmlparser.parserapplications.SiteCapturer$LocalLinkTag org.htmlparser.parserapplications.SiteCapturer$LocalFrameTag org.htmlparser.parserapplications.SiteCapturer$LocalImageTag org.htmlparser.parserapplications.filterbuilder.FilterBuilder org.htmlparser.parserapplications.filterbuilder.HtmlTreeModel org.htmlparser.parserapplications.filterbuilder.SubFilterList org.htmlparser.filters.CssSelectorNodeFilter$AttribMatchFilter org.htmlparser.filters.CssSelectorNodeFilter$HasAncestorFilter org.htmlparser.parserapplications.SiteCapturer$LocalBaseHrefTag org.htmlparser.parserapplications.filterbuilder.HtmlTreeCellRenderer org.htmlparser.parserapplications.filterbuilder.wrappers.OrFilterWrapper org.htmlparser.parserapplications.filterbuilder.layouts.NullLayoutManager org.htmlparser.parserapplications.filterbuilder.wrappers.AndFilterWrapper org.htmlparser.parserapplications.filterbuilder.wrappers.NotFilterWrapper org.htmlparser.parserapplications.filterbuilder.wrappers.RegexFilterWrapper org.htmlparser.parserapplications.filterbuilder.wrappers.StringFilterWrapper org.htmlparser.parserapplications.filterbuilder.layouts.VerticalLayoutManager org.htmlparser.parserapplications.filterbuilder.wrappers.TagNameFilterWrapper org.htmlparser.parserapplications.filterbuilder.wrappers.HasChildFilterWrapper org.htmlparser.parserapplications.filterbuilder.wrappers.HasParentFilterWrapper org.htmlparser.parserapplications.filterbuilder.wrappers.NodeClassFilterWrapper org.htmlparser.parserapplications.filterbuilder.wrappers.HasSiblingFilterWrapper org.htmlparser.parserapplications.filterbuilder.wrappers.HasAttributeFilterWrapper
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值