htmlparser 解析HTML 思路

happyzhangyin 2012-08-28

HtmlParser解析HTML

HTML正则表达式VBVB.NET搜索引擎.

1.可以在任何.net语言中使用(C#,VB.net,J#等)

2.可以解析几乎所有的Html标签,并且可以通过标签类别、属性或正则表达式来搜索标签。有些甚至在Java版本中无法支持的标签也在这个版本中得到了支持。

3.设置可扩展的过滤器来过滤结果集中不需要的标签。

4.高性能的API接口使得你能处理许多常见的问题,如:哪些是页面中的外部链接?哪些是图片?哪些是不同的表格?页面中有错误的链接吗等等问题。

5.一个基于Http协议引擎的配置文件使得你能通过一个指定的URL地址来获得该页面内容。该爬虫可以遵循robot.txt协议文件来获得组织和允许访问的列表。

6.Http协议引擎能够完整地处理来自任何站点的反馈。

三、词法分析的工作原理

HTMLParser的词法分析器对HTML进行了4级封装,从低级到高级的顺序为:ParserStream、Source、Page、Lexer。ParserStream负责从文件中获取二进制数据,但不做任何处理。Source把二进制文件转换成相应的字符序列,存储一组未加工的字符序列。Page可以看成是一个string数组,按行存储一个Source文本的每一行第一个字符开始的位置索引。Lexer包含了词法分析的代码,从Page里读取字符串,用Cursor记录当前字符所在位置,通过状态机来生成Nodes节点。

Lexer中真正执行词法分析的是NextCode()方法,它每次词都查找返回下一个Node节点,直到Page结束。算法描述如下:

1.读入一个字符,判断是否已是页尾,是则返回null。

2.判断是否是"<",如果是,则可能是标签入口,需读取下一字符确认。

3.如果都不是,ParserString状态机开始解析一个StringNode,如果是"<",继续读取下一字符。

4.判断是否到页尾,是则产生一个StringNode返回。

5.如果读取到"%",则说明是JSP标签,进入JSP状态机去解析。

6.如果读取到"?",则说明是XML标签,进入XML状态机去解析。

7.如果读取到"/"或任何字母,说明是Tag标签,进入Tag标签状态机去解析。

8.如果读取到"!",则说明进入了一个注释标签,需要再读取一个字符,如果到页尾,则产生一个StringNode返回,如果字符为">"则生成一个RemarkNode返回,否则回退一个字符,再判断字符如果是"-"则回退一个字符,进入Remark状态机去解析,如果不是,则回退一个字符进入Tag状态机去解析。

四、三种使用方法的比较

1.使用Lexer词法分析器直接解析HTML。

这样的方法较为底层,只能返回一个线性的Node节点序列,通过Lexer.NextNode()方法获得下一个Node的信息。虽然不够方便,但有时可完成一些较为灵活的工作。

调用的方法是(传入string类型的html代码):

Lexerlexer=newLexer(htmlcode);

INodenode=lexer.NextNode();

Console.Write(node.ToString());

返回结果是该页面的第一个标签"html"的Node结点信息。

2.使用Filter结点过滤模式。

如果你有一些很明确的结点需要提取,那么就该使用Filter结点过滤模式。系统定义了17种具体的Filter,根据不同的过滤条件来获得需要的结点。包括依据结点父子关系的Filter,连接Filter组合的Filter,依据网页内容匹配情况的filter,等等。我们也可以继承Filter做自己的Filter来提取节点。

NodeListnodeList=myParser.parse(someFilter);

解析之后,我们可以采用:

INode[]nodes=nodeList.toNodeArray();

来获取节点数组,也可以直接访问:

INodenode=nodeList.elementAt(i);

来获取Node。

另外,在Filter后得到NodeList以后,我们仍然可以使用nodeList.extractAllNodesThatMatch(someFilter)来进一步过滤,同时又可以用nodeList.visitAllNodesWith(someVisitor)来做进一步的访问。

3.使用Visitor结点访问模式

如果你希望HTMLParser遍历所有的结点,并按结点的不同类型(StringNode、RemarkNode、TagNode)和不同的访问过程来进行不同操作的话,可以使用Visitor模式。NodeVisitor是一个抽象类,分别定义了如下方法:

BeginParsing():解析前进行的操作

VitisTag():访问到开始标签时的操作

VisitEndTag():访问到结束标签时的操作

VisitStringNode():访问到文本结点时的操作

VisitRemarkNode():访问注释结点时的操作

自己定义一个类并继承NodeVisitor类,实现以上几个方法,即完成Visitor模式的访问类。系统也提供了7个具体的结点访问类,具体见上文提供的类库文档。不过这7个类并不实用,大多数的功能还需要自己来扩充定义。调用方法:

Parserparser=Parser.CreateParser((htmlcode),"GBK");//传入string类型的html代码

NodeVisitorvisitor=newLinkFindingVisitor(linktext);//以链接查找的Visitor举例

parser.VisitAllNodesWith(visirot);

灵活使用以上三种模式的结合,相信就可以提取到任何我们所需要的信息了。

相关推荐