正则表达式HTMLParser使用详解.ppt

上传人:牧羊曲112 文档编号:5776769 上传时间:2023-08-19 格式:PPT 页数:80 大小:377.50KB
返回 下载 相关 举报
正则表达式HTMLParser使用详解.ppt_第1页
第1页 / 共80页
正则表达式HTMLParser使用详解.ppt_第2页
第2页 / 共80页
正则表达式HTMLParser使用详解.ppt_第3页
第3页 / 共80页
正则表达式HTMLParser使用详解.ppt_第4页
第4页 / 共80页
正则表达式HTMLParser使用详解.ppt_第5页
第5页 / 共80页
点击查看更多>>
资源描述

《正则表达式HTMLParser使用详解.ppt》由会员分享,可在线阅读,更多相关《正则表达式HTMLParser使用详解.ppt(80页珍藏版)》请在三一办公上搜索。

1、Java正则表达式入门+HTMLParser使用详解,一、Java正则表达式入门 众所周知,在程序开发中,难免会遇到需要匹配、查找、替换、判断字符串的情况发生,而这些情况有时又比较复杂,如果用纯编码方式解决,往往会浪费程序员的时间及精力。因此,学习及使用正则表达式,便成了解决这一矛盾的主要手段。大家都知道,正则表达式是一种可以用于模式匹配和替换的规范,一个正则表达式就是由普通的字符(例如字符a到z)以及特殊字符(元字符)组成的文字模式,它 用以描述在查找文字主体时待匹配的一个或多个字符串。正则表达式作为一个模板,将某个字符模式与所搜索的字符串进行匹配。自从jdk1.4推出包,就为我们提供了很好

2、的JAVA正则表达式应用平台。,说明,转义符,a,f,响铃符=x07,换页符=x0C,换页符,n,响铃符=x07,换行(u000A),r,回车符=x0D,回车(u000D),t,制表符=x09,间隔(u0009),v,垂直制表符=x0B,e,ESC 符=x1B,Escape,x20,使用两位十六进制表示形式,可与该编号的字符匹配,u002B,使用四位十六进制表示形式,可与该编号的字符匹配,x20A060,使用任意位十六进制表示形式,可与该编号的字符匹配,说明,字符,$,匹配输入字符串的开始位置。要匹配 字符本身,请使用,匹配输入字符串的结尾位置。要匹配“$”字符本身,请使用“$”,(),标记一

3、个子表达式的开始和结束位置。要匹配小括号,请使用(和),用来自定义能够匹配 多种字符 的表达式。要匹配中括号,请使用 和,修饰匹配次数的符号。要匹配大括号,请使用 和,.,匹配除了换行符(n)以外的任意一个字符。要匹配小数点本身,请使用.,?,修饰匹配次数为 0 次或 1 次。要匹配?字符本身,请使用?,+,修饰匹配次数为至少 1 次。要匹配+字符本身,请使用+,*,修饰匹配次数为 0 次或任意次。要匹配*字符本身,请使用*,|,左右两边表达式之间 或 关系。匹配|本身,请使用|,说明,字符集合,.,w,小数点可以匹配除了换行符(n)以外的任意一个字符,可以匹配任何一个字母或者数字或者下划线,

4、单独字符 a-zA-Z_0-9,W,W大写,可以匹配任何一个字母或者数字或者下划线以外的字符,非单独字符 a-zA-Z_0-9,s,可以匹配空格、制表符、换页符等空白字符的其中任意一个,空白符号 tnx0Bfr,S,S大写,可以匹配任何一个空白字符以外的字符,非空白符号tnx0Bfr,d,可以匹配任何一个 09 数字字符,数字 等价于0-9,D,D大写,可以匹配任何一个非数字字符,非数字 等价于0-9,字符集合可以匹配“多个字符”其中任意一个字符的正则表达式。虽然是“多个字符”,但每次只能匹配其中一个。DEELX 正则表达式中标准的字符集合有:,说明,限定符,n,m,n,表达式固定重复n次,比

5、如:w2 相当于 ww,表达式尽可能重复n次,至少重复m次:ba1,3可以匹配 ba或baa或baaa,m,表达式尽可能的多匹配,至少重复m次:“wd2,”可以匹配a12,x456.,?,表达式尽可能匹配1次,也可以不匹配,相当于 0,1,+,表达式尽可能的多匹配,至少匹配1次,相当于 1,*,表达式尽可能的多匹配,最少可以不匹配,相当于 0,匹配次数限定符使被修饰的表达式可多次重复匹配的修饰符。可使被修饰的表达式重复固定次数,也可以限定一定的重复匹配的次数范围。在限定符之后的表达式能够匹配成功的情况下,不定次数的限定符总是尽可能的多匹配。如果之后的表达式匹配失败,限定符可适当“让出”能够匹配

6、的字符,以使整个表达式匹配成功。这种模式就叫“贪婪模式”。,说明,限定符,m,n?,m,?,表达式尽量只匹配m次,最多重复n次。,表达式尽量只匹配m次,最多可以匹配任意次。,?,表达式尽量不匹配,最多匹配1次,相当于 0,1?,+?,表达式尽量只匹配1次,最多可匹配任意次,相当于 1,?,*?,表达式尽量不匹配,最多可匹配任意次,相当于 0,?,“勉强模式”限定符:在限定符之后添加问号(?),则使限定符成为“勉强模式”。勉强模式的限定符,总是尽可能少的匹配。如果之后的表达式匹配失败,勉强模式也可以尽可能少的再匹配一些,以使整个表达式匹配成功。,说明,限定符,m,n+,m,+,表达式尽可能重复n

7、次,至少重复m次。,表达式尽可能的多匹配,至少重复m次。,?+,表达式尽可能匹配1次,也可以不匹配,相当于 0,1+,+,表达式尽可能的多匹配,至少匹配1次,相当于 1,+,*+,表达式尽可能的多匹配,最少可以不匹配,相当于 0,+,“占有模式”限定符:在限定符之后添加加号(+),则使限定符成为“占有模式”。占有模式的限定符,总是尽可能多的匹配。与“贪婪模式”不同的是,即使之后的表达式匹配失败,“占有模式”也不会“让出”自己能够匹配的字符。,转义字符 Q.E使用 Q 开始,E 结束,可使中间的标点符号失去特殊意义,将中间的字符作为普通字符。例如:Q(a+b)*3E 可匹配文本“(a+b)*3”

8、。,因为正则表达式是一个很庞杂的体系,所以我仅例举些入门的概念,更多的请参阅相关书籍及自行摸索。,b 一个单词的边界B 一个非单词的边界G 前一个匹配的结束为限制开头java 条件限制为以Java为开头字符$为限制结尾java$条件限制为以java为结尾字符.条件限制除n以外任意一个单独字符java.条件限制为java后除换行外任意两个字符加入特定限制条件a-z 条件限制在小写a to z范围中一个字符A-Z 条件限制在大写A to Z范围中一个字符a-zA-Z 条件限制在小写a to z或大写A to Z范围中一个字符,0-9 条件限制在小写0 to 9范围中一个字符0-9a-z 条件限制在

9、小写0 to 9或a to z范围中一个字符0-9a-z 条件限制在小写0 to 9或a to z范围中一个字符(交集)中加入后加再次限制条件a-z 条件限制在非小写a to z范围中一个字符A-Z 条件限制在非大写A to Z范围中一个字符a-zA-Z 条件限制在非小写a to z或大写A to Z范围中一个字符0-9 条件限制在非小写0 to 9范围中一个字符0-9a-z 条件限制在非小写0 to 9或a to z范围中一个字符0-9a-z 条件限制在非小写0 to 9或a to z范围中一个字符(交集)在限制条件为特定字符出现0次以上时,可以使用*J*0个以上J.*0个以上任意字符,J.

10、*D J与D之间0个以上任意字符在限制条件为特定字符出现1次以上时,可以使用+J+1个以上J.+1个以上任意字符J.+D J与D之间1个以上任意字符在限制条件为特定字符出现有0或1次以上时,可以使用?JA?J或者JA出现限制为连续出现指定次数字符aJ2 JJJ3 JJJ文字a个以上,并且a,J3,JJJ,JJJJ,JJJJJ,?(3次以上J并存),文字个以上,b个以下a,bJ3,5 JJJ或JJJJ或JJJJJ两者取一|J|A J或AJava|Hello Java或Hello()中规定一个组合类型比如,我查询index中间的数据,可写作+href=?(*)?*(.+?)在使用Ppile函数时,

11、可以加入控制正则表达式的匹配行为的参数:Pattern Ppile(String regex,int flag),flag的取值范围如下:Pattern.CANON_EQ 当且仅当两个字符的正规分解(canonical decomposition)都完全相同的情况下,才认定匹配。比如用了这个标志之后,表达式au030A会匹配?。默认情况下,不考虑规 范相等性(canonical equivalence)。Pattern.CASE_INSENSITIVE(?i)默认情况下,大小写不明感的匹配只适用于US-ASCII字符集。这个标志能让表达式忽略大小写进行匹配。要想对Unicode字符进行大小不明

12、感的匹 配,只要将UNICODE_CASE与这个标志合起来就行了。Pattern.COMMENTS(?x)在这种模式下,匹配时会忽略(正则表达式里的)空格字符,(译者注:不是指表达式里的s,而是指表达式里的空格,tab,回车之类)。注释从#开始,一直到这行结束。可以通过嵌入式的标志来启用Unix行模式。Pattern.DOTALL(?s)在这种模式下,表达式.可以匹配任意字符,包括表示一行的结束符。默认情况下,表达式.不匹配行的结束符。Pattern.MULTILINE(?m)在这种模式下,和$分别匹配一行的开始和结束。此外,仍然匹配字符串的开始,$也匹配字符串的结束。默认情况下,这两个表达式

13、仅仅匹配字符串的开始和结束。Pattern.UNICODE_CASE(?u)在这个模式下,如果你还启用了CASE_INSENSITIVE,*,标志,那么它会对Unicode字符进行大小写不明感的匹配。默认情况下,大小写不敏感的匹配只适用于US-ASCII字符集。Pattern.UNIX_LINES(?d)在这个模式下,只有n才被认作一行的中止,并且与.,以及$进行匹配。抛开空泛的概念,下面写出几个简单的Java正则用例:比如,在字符串包含验证时/查找以Java开头,任意结尾的字符串Pattern pattern=Ppile(Java.*);Matcher matcher=pattern.mat

14、cher(Java不是人);boolean b=matcher.matches();/当条件满足时,将返回true,否则返回falseSystem.out.println(b);,以多条件分割字符串时Pattern pattern=Ppile(,|+);String strs=pattern.split(Java Hello World Java,Hello,World|Sun);for(int i=0;istrs.length;i+)System.out.println(strsi);文字替换(首次出现字符)Pattern pattern=Ppile(正则表达式);Matcher match

15、er=pattern.matcher(正则表达式 Hello World,正则表达式 Hello World);/替换第一个符合正则的数据System.out.println(matcher.replaceFirst(Java);,文字替换(全部)Pattern pattern=Ppile(正则表达式);Matcher matcher=pattern.matcher(正则表达式 Hello World,正则表达式 Hello World);/替换第一个符合正则的数据System.out.println(matcher.replaceAll(Java);文字替换(置换字符)Pattern pat

16、tern=Ppile(“正则表达式”);Matcher matcher=pattern.matcher(“正则表达式 Hello World,正则表达式 Hello World”);StringBuffer sbr=new StringBuffer();while(matcher.find()matcher.appendReplacement(sbr,“Java”);,matcher.appendTail(sbr);System.out.println(sbr.toString();验证是否为邮箱地址String email=“w.-+(w-+.)+w-+”;String str=”;Patt

17、ern pattern=Ppile(email,Pattern.CASE_INSENSITIVE);Matcher matcher=pattern.matcher(str);System.out.println(matcher.matches();比较严格的:email=(0-9a-zA-Z(-.w*0-9a-zA-Z)*(0-9a-zA-Z)+(-w*0-9a-zA-Z)*.)+a-zA-Z2,9)$去除html标记Pattern pattern=Ppile(,Pattern.DOTALL);,Matcher matcher=pattern.matcher(主页);String string

18、=matcher.replaceAll();System.out.println(string);查找html中对应条件字符串Pattern pattern=Ppile(href=(.+?);Matcher matcher=pattern.matcher(主页);if(matcher.find()System.out.println(matcher.group(1);截取http:/地址/截取urlPattern pattern=Ppile(http:/|https:/)1w.-/:+);,Matcher matcher=pattern.matcher(dsdsdsfdf);StringBuf

19、fer buffer=new StringBuffer();while(matcher.find()buffer.append(matcher.group();buffer.append(rn);System.out.println(buffer.toString();替换指定中文字String str=Java目前的发展史是由0年-1年;String object=new String0,1995,new String1,2007;,System.out.println(replace(str,object);public static String replace(final String

20、 sourceString,Object object)String temp=sourceString;for(int i=0;iobject.length;i+)String result=(String)objecti;Pattern pattern=Ppile(result0);Matcher matcher=pattern.matcher(temp);temp=matcher.replaceAll(result1);return temp;,读取页面链接和内容:public String newsListRegExp=+href=?(*)?*(.+?);newsListRegExp=

21、+hrefs*=*s*(s|+)*(;public void getLinks(String content)pattern=java.util.regex.Ppile(newsListRegExp,java.util.regex.Pattern.CASE_INSENSITIVE);matcher=pattern.matcher(content);while(matcher.find()String link=matcher.group(1);String text=matcher.group(2);System.out.println(link+text);,Java正则的功用还有很多,事实

22、上只要是字符处理,就没有正则做不到的事情存在。(当然,正则解释时较耗时间就是了!),二、HTMLParser使用详解,HTMLParser使用详解(1)-初始化Parser,在研究搜索引擎的开发中,对于HTML网页的处理是核心的一个环节。网上有很多开源的代码,对于Java来说,HTMLParser是比较著名并且得到广泛应用的一个。HTMLParser的主页是http:/,最后的更新是2006年9月的1.6版。不过没关系,HTML的内容已经很久没有大的变化了,HTMLParser处理起来基本没有任何问题。,HTMLParser的核心模块是类,这个类实际完成了对于HTML页面的分析工作。这个类有下

23、面几个构造函 数:public Parser();public Parser(Lexer lexer,ParserFeedback fb);public Parser(URLConnection connection,ParserFeedback fb)throws ParserException;public Parser(String resource,ParserFeedback feedback)throws ParserException;public Parser(String resource)throws ParserException;public Parser(Lexer

24、lexer);public Parser(URLConnection connection)throws ParserException;和一个静态类 public static Parser createParser(String html,String charset);,对于大多数使用者来说,使用最多的是通过一个URLConnection或者一个保存有网页内容的字符串来初始化Parser,或者使用静态函数来生成一个Parser对象。ParserFeedback的代码很简单,是针对调试和跟踪分析过程的,一般不需要改变。而使用Lexer则是一个相对比较高级的话题,放到以后再讨论吧。这里比较有

25、趣的一点是,如果需要设置页面的编码方式的话,不使用Lexer就只有静态函数一个方法了。对于大多数中文页面来说,好像这是应该用得比较多的一个方法。,HTMLParser使用详解(2)-Node内容,HTMLParser将解析过的信息保存为一个树的结构。Node是信息保存的数据类型基础。请看Node的定义:public interface Node extends Cloneable;Node中包含的方法有几类:对于树型结构进行遍历的函数,这些函数最容易理解:Node getParent():取得父节点NodeList getChildren():取得子节点的列表,Node getFirstChi

26、ld():取得第一个子节点Node getLastChild():取得最后一个子节点Node getPreviousSibling():取得前一个兄弟(不好意思,英文是兄弟姐妹,直译太麻烦而且不符合习惯,对不起女同胞了)Node getNextSibling():取得下一个兄弟节点取得Node内容的函数:String getText():取得文本String toPlainTextString():取得纯文本信息。String toHtml():取得HTML信息(原始HTML)String toHtml(boolean verbatim):取得HTML信息(原始HTML)String toSt

27、ring():取得字符串信息(原始HTML)Page getPage():取得这个Node对应的Page对象,int getStartPosition():取得这个Node在HTML页面中的起始位置int getEndPosition():取得这个Node在HTML页面中的结束位置用于Filter过滤的函数:void collectInto(NodeList list,NodeFilter filter):基于filter的条件对于这个节点进行过滤,符合条件的节点放到list中。用于Visitor遍历的函数:void accept(NodeVisitor visitor):对这个Node应用v

28、isitor用于修改内容的函数,这类用得比较少:void setPage(Page page):设置这个Node对应的Page对象void setText(String text):设置文本void setChildren(NodeList children):设置子节点列表,其他函数:void doSemanticAction():执行这个Node对应的操作(只有少数Tag有对应的操作)Object clone():接口Clone的抽象函数。主要注意一下,getText,toPlainTextString,toHtml 区别String a=猫扑hi来点不一样;Parser p=Parser

29、.createParser(a,UTF-8);try for(NodeIterator it=p.elements();it.hasMoreNodes();)Node node=it.nextNode();System.out.println(node.getText()+$+node.toPlainTextString()+$+node.toHtml();catch(ParserException e)/TODO Auto-generated catch blocke.printStackTrace();输出:div id=hi$猫扑hi$猫扑hia class=link href=$来点不

30、一样$来点不一样,下面是用于测试的HTML文件:白泽居-白泽居-白泽居-白泽居-,toPlainTextString是把用户可以看到的内容都包含了。有趣的有两点,一是标签中的Title内容是在plainText中的,可能在标题中可见的也算可见吧。另外就是象前面说的,HTML内容中的换行符什么的,也都成了plainText,这个逻辑上好像有点问题。另外可能大家发现toHtml,toHtml(true)和toHtml(false)的结果没什么区别。实际也是这样的,如果,跟踪HTMLParser的代码就可以发现,Node的子类是AbstractNode,其中实现了toHtml()的代码,直接调用to

31、Html(false),而AbstractNode的三个子类RemarkNode,TagNode和TextNode中,toHtml(boolean verbatim)的实现中,都没有处理verbatim参数,所以三个函数的结果是一模一样的。如果你不需要实现你自己的什么特殊处理,简单使用toHtml就可以了。,HTML的Node类继承关系如下图这个是从别的文章Copy的):,AbstractNodes是Node的直接子类,也是一个抽象类。它的三个直接子类实现是RemarkNode,用于保存注释。在输出结果的toString部分中可以看到有一个Rem(3456,2,3566,13):这是注释,就是

32、一个RemarkNode。TextNode也很简单,就是用户可见的文字信息。TagNode是最复杂的,包含了HTML语言中的所有标签,而且可以扩展(扩展 HTMLParser 对自定义标签的处理能力)。TagNode包含两类,一类是简单的Tag,实际就是不能包含其他Tag的标签,只能做叶子节点。另一类是CompositeTag,就是可以包含其他Tag,是分支节点。,遍历了网页的内容以后,以树(森林)结构保存了结果。HTMLParser访问结果内容的方法有两种。使用Filter和使用Visitor。(一)Filter类 顾名思义,Filter就是对于结果进行过滤,取得需要的内容。HTMLPars

33、er在包之内一共定义了16个不同的Filter,也可以分为几类。,HTMLParser使用详解(3)-通过Filter访问内容,判断类Filter:TagNameFilterHasAttributeFilterHasChildFilterHasParentFilterHasSiblingFilterIsEqualFilter逻辑运算Filter:AndFilterNotFilterOrFilterXorFilter,其他Filter:NodeClassFilterStringFilterLinkStringFilterLinkRegexFilterRegexFilterCssSelectorN

34、odeFilter所有的Filter类都实现了接口。这个接口只有一个主要函数:boolean accept(Node node);各个子类分别实现这个函数,用于判断输入的Node是否符合这个Filter的过滤条件,如果符合,返回true,否则返回false。,(二)判断类Filter HTMLParser使用入门(2)-Node内容,自己添加import部分)public static void main(String args)try Parser parser=new Parser(HttpURLConnection)(new URL(http:/127.0.0.1:8080/HTMLPa

35、rserTester.html).openConnection();/这里是控制测试的部分,后面的例子修改的就是这个地方。NodeFilter filter=new TagNameFilter(DIV);NodeList nodes=parser.extractAllNodesThatMatch(filter);,if(nodes!=null)for(int i=0;i nodes.size();i+)Node textnode=(Node)nodes.elementAt(i);message(getText:+textnode.getText();message(=);catch(Excep

36、tion e)e.printStackTrace();输出结果:getText:div id=top_main,=getText:div id=logoindex=可以看出文件中两个Div节点都被取出了。下面可以针对这两个DIV节点进行操作2.2 HasChildFilter 下面让我们看看HasChildFilter。刚刚看到这个Filter的时候,我想当然地认为这个Filter返回的是有Child的Tag。直接初始化了一个NodeFilter filter=new HasChildFilter();,结果调用NodeList nodes=parser.extractAllNodesThat

37、Match(filter);的时候HasChildFilter内部直接发生NullPointerException。读了一下HasChildFilter的代码,才发现,实际HasChildFilter是返回有符合条件的子节点的节点,需要另外一个Filter作为过滤子节点的参数。缺省的构造函数虽然可以初始化,但是由于子节点的Filter是null,所以使用的时候发生了Exception。从这点来看,HTMLParser的代码还有很多可以优化的的地方。呵呵。,修改代码:NodeFilter innerFilter=new TagNameFilter(DIV);NodeFilter filter=n

38、ew HasChildFilter(innerFilter);NodeList nodes=parser.extractAllNodesThatMatch(filter);输出结果:getText:body=getText:div id=top_main=可以看到,输出的是两个有DIV子Tag的Tag节点。(body有子节点DIV top_main,top_main有子节点logoindex。,注意HasChildFilter还有一个构造函数:public HasChildFilter(NodeFilter filter,boolean recursive)如果recursive是false,

39、则只对第一级子节点进行过滤。比如前面的例子,body和top_main都是在第一级的子节点里就有DIV节点,所以匹配上了。如果我们用下面的方法调用:NodeFilter filter=new HasChildFilter(innerFilter,true);输出结果:getText:html xmlns=http:/www.w3.org/1999/xhtml=getText:body=getText:div id=top_main=,可以看到输出结果中多了一个html xmlns=http:/www.w3.org/1999/xhtml,这个是整个HTML页面的节点(根节点),虽然这个节点下直接

40、没有DIV节点,但是它的子节点body下面有DIV节点,所以它也被匹配上了。2.3 HasAttributeFilter HasAttributeFilter有3个构造函数:public HasAttributeFilter();public HasAttributeFilter(String attribute);public HasAttributeFilter(String attribute,String value);这个Filter可以匹配出包含制定名字的属性,或者制定属性为指定值的节点。还是用例子说明比较容易。,调用方法1:NodeFilter filter=new HasAtt

41、ributeFilter();NodeList nodes=parser.extractAllNodesThatMatch(filter);输出结果:什么也没有输出。调用方法2:NodeFilter filter=new HasAttributeFilter(id);NodeList nodes=parser.extractAllNodesThatMatch(filter);,输出结果:getText:div id=top_main=getText:div id=logoindex=调用方法3:NodeFilter filter=new HasAttributeFilter(id,logoin

42、dex);NodeList nodes=parser.extractAllNodesThatMatch(filter);输出结果:getText:div id=logoindex=很简单吧。呵呵,2.4 其他判断列Filter HasParentFilter和HasSiblingFilter的功能与HasChildFilter类似,大家自己试一下就应该了解了。IsEqualFilter的构造函数参数是一个Node:public IsEqualFilter(Node node)mNode=node;accept函数也很简单:public boolean accept(Node node)retu

43、rn(mNode=node);不需要过多说明了。,(三)逻辑运算Filter(四)其他Filter:HTMLParser使用入门(2)-Node内容 中我们已经了解了Node的不同类型,这个Filter就可以针对类型进行过滤。测试代码:NodeFilter filter=new NodeClassFilter(RemarkNode.class);NodeList nodes=parser.extractAllNodesThatMatch(filter);输出结果:getText:这是注释=可以看到只有RemarkNode(注释)被输出了。,4.2 StringFilter 这个Filter用于

44、过滤显示字符串中包含制定内容的Tag。注意是可显示的字符串,不可显示的字符串中的内容(例如注释,链接等等)不会被显示。修改一下例子代码:白泽居-title-,白泽居-字符串白泽居-链接文本-白泽居-字符串2-,测试代码:NodeFilter filter=new);NodeList nodes=parser.extractAllNodesThatMatch(filter);输出结果:getText:白泽居-title-=getText:白泽居-字符串1-=getText:白泽居-链接文本-=,getText:白泽居-字符串2-=可以看到包含title,两个内容字符串和链接的文本字符串的Tag都

45、被输出了,但是注释和链接Tag本身没有输出。4.3 LinkStringFilter 这个Filter用于判断链接中是否包含某个特定的字符串,可以用来过滤出指向某个特定网站的链接。测试代码:NodeFilter filter=new);NodeList nodes=parser.extractAllNodesThatMatch(filter);,输出结果:getText:a href=http:/=4.4 其他几个Filter 其他几个Filter也是根据字符串对不同的域进行判断,与前面这些的区别主要就是支持正则表达式。这个不在本文的讨论范围以内,大家可以自己实验一下。前面介绍的都是简单的Fi

46、lter,只能针对某种单一类型的条件进行过滤。HTMLParser支持对于简单类型的Filter进行组合,从而实现复杂的条件。原理和一般编程语言的逻辑运算是一样的。,3.1 AndFilter AndFilter可以把两种Filter进行组合,只有同时满足条件的Node才会被过滤。测试代码:NodeFilter filterID=new HasAttributeFilter(“id”);NodeFilter filterChild=new HasChildFilter(filterA);NodeFilter filter=new AndFilter(filterID,filterChild);

47、输出结果:getText:div id=“logoindex”=,3.2 OrFilter 把前面的AndFilter换成OrFilter测试代码:NodeFilter filterID=new HasAttributeFilter(id);NodeFilter filterChild=new HasChildFilter(filterA);NodeFilter filter=new OrFilter(filterID,filterChild);输出结果:getText:div id=top_main=getText:div id=logoindex=,3.3 NotFilter 把前面的An

48、dFilter换成NotFilter测试代码:NodeFilter filterID=new HasAttributeFilter(id);NodeFilter filterChild=new HasChildFilter(filterA);NodeFilter filter=new NotFilter(new OrFilter(filterID,filterChild);输出结果:getText:!DOCTYPE html PUBLIC-/W3C/DTD XHTML 1.0 Transitional/EN http:/www.w3.org/TR/xhtml1/DTD/xhtml1-trans

49、itional.dtd=getText:,=getText:head=getText:meta http-equiv=Content-Type content=text/html;charset=gb2312=getText:title=getText:白泽居-=getText:/title=getText:/head,=getText:=getText:html xmlns=http:/www.w3.org/1999/xhtml=getText:=getText:body=getText:=getText:,=getText:=getText:这是注释=getText:白泽居-=getTex

50、t:a href=http:/=getText:白泽居-=getText:/a,=getText:=getText:/div=getText:白泽居-=getText:/div=getText:,=getText:/body=getText:=getText:/html=getText:=除了前面3.2中输出的几个Tag,其余的Tag都在这里了。,3.4 XorFilter 把前面的AndFilter换成NotFilter测试代码:NodeFilter filterID=new HasAttributeFilter(id);NodeFilter filterChild=new HasChild

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 生活休闲 > 在线阅读


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号