├── HtmlParser.cpp ├── HtmlParser.h ├── README.md ├── htmlua.cpp ├── htmlua.def ├── htmlua.dll ├── htmlua.dsp ├── htmlua.dsw ├── htmlua.h └── test.lua /HtmlParser.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liigo/htmlua/8ead93e64966c8ccb04d5013178f617f467acfe3/HtmlParser.cpp -------------------------------------------------------------------------------- /HtmlParser.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liigo/htmlua/8ead93e64966c8ccb04d5013178f617f467acfe3/HtmlParser.h -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | htmlua 2 | ====== 3 | 4 | Lua's C module for parsing html text, wrapper of liigo::HtmlParser 5 | 6 | LUA的HTML解析库,C模块,封装自C++的库 [liigo::HtmlParser](https://github.com/liigo/html-parser)。 7 | 8 | ###〇、基本概念 9 | 10 | 本HTML解析器把HTML文本解析为一组有序的节点(Node)。各节点分为不同的类型,记录了不同的信息。 11 | 节点的类型有:开始标签(如<a href="...">)、结束标签(如</a>)、文本、注释等。 12 | 开始标签和结束标签都有一个标签名称(tagname,如上例的"a"),相应的有一个标签类型(tagtype,用整数标识标签)。 13 | 开始标签节点往往有一系列属性(Attributes,如前例中的"href")。 14 | 15 | 本文第四节将专门介绍节点类型和标签类型。更多信息请参考[我CSDN博客上的文章](http://blog.csdn.net/liigo/article/details/6153829)。 16 | 17 | ###一、加载htmlua库,创建parser解析器对象 18 | 19 | local html = require "htmlua" 20 | 21 | 该html对象(可自由命名)有以下两个函数: 22 | 23 | html.newparser(fn1,fn2) -- 创建解析器对象,两参数均可省略(详见下文第五节),返回parser 24 | html.deleteparser(parser) -- 删除解析器对象,参数为parser,无返回值 25 | 26 | 该html对象还有一个自动创建好的 parser 成员,可供直接使用,无需显式创建和删除。 27 | 28 | ###二、parser解析器对象,解析HTML文本 29 | 30 | parser解析器有以下方法(需首先传入parser自身作为第一个参数): 31 | 32 | parser:parse(html,[parseAttr]) -- 解析HTML文本,参数1是HTML文本,参数2指定是否解析节点属性(默认为true),无返回值 33 | parser:nodecount() -- 返回解析后的节点个数 34 | parser:node(index) -- 返回解析后的指定索引处的节点对象,参数是节点索引(>=1,<=nodecount()),返回值是node对象(索引非法时返回nil) 35 | parser:ipairs() -- 用于支持for循环顺序遍历节点,如:for index,node in parser:ipairs() do ... 36 | 37 | 借助于 parser:ipairs() 方法,可以用 for 循环顺序遍历 node 节点对象: 38 | 39 | parser:parse("
xxx...")
40 | for index,node in parser:ipairs() do
41 | print("node:", index, node.tagname, node.text)
42 | end
43 |
44 | ###三、node节点对象,获取节点信息
45 |
46 | node对象有以下成员:
47 |
48 | node.type -- 节点类型(int),可为 htmlnode.START_TAG, htmlnode.END_TAG... 等常量值之一,详见第四节htmlnode
49 | node.text -- 节点文本(string)
50 | node.tagname -- 标签名称(string)
51 | node.tagtype -- 标签类型(int),可为 htmltag.A, htmltag.DIV, htmltag.IMG... 等常量值之一,详见第四节htmltag
52 | node.attrcount -- 属性个数(int)
53 | node.iscdata -- 是否CDATA区块(bool)
54 | node.isselfclosing -- 是否自结束标签(bool)(例如
为自结束标签)
55 |
56 | node对象有以下方法(需首先传入node自身作为第一个参数):
57 |
58 | node:attr(index/name) -- 取指定属性值。如果参数是属性名(string),返回属性值(string);如果参数是属性索引(>=1,<=attrcount),返回属性名(string)和属性值(string);如果参数指定的属性不存在,返回两个nil。
59 | node:pairs() -- 用于支持for循环遍历属性,如 for name,value in node:pairs() do ...
60 | node:parseattr() -- 解析节点属性,无参数无返回值,解析结果存入node对象中。如果先前已经解析过,不会重复解析。
61 |
62 | 借助于 node:pairs() 方法,可以用 for 循环遍历节点属性:
63 |
64 | local node1 = parser:node(1)
65 | for name,value in node1:pairs() do
66 | print("attr:", name, value)
67 | end
68 |
69 | 注意,操作node的过程中需保证parser对象始终有效,且没有调用parser:parse()执行下一次解析。
70 |
71 | ###四、节点类型和标签类型
72 |
73 | 节点类型用一个整数来表示,本库已事先定义了如下节点类型常量:
74 |
75 | htmlnode = {
76 | START_TAG = 1, --开始标签,如 或
77 | END_TAG = 2, --结束标签,如
78 | CONTENT = 3, --内容: 介于开始标签和/或结束标签之间的普通文本
79 | REMARKS = 4, --注释:
80 | UNKNOWN = 5, --未知的节点类型
81 | _USER_ = 10, --用户定义的其他节点类型值应大于_USER_,以确保不与上面定义的常量值重复
82 | }
83 |
84 | 使用方法: if(nodetype == htmlnode.START_TAG) ...
85 |
86 | 标签类型也用一个整数来表示,本库已事先定义了如下标签类型常量:
87 |
88 | htmltag = {
89 | UNKNOWN = 0, --表示未经识别的标签类型,参见HtmlParser.onIdentifyHtmlTag()
90 | SCRIPT=1, STYLE=2, TEXTAREA=3, --出于解析需要必须识别