GithubHelp home page GithubHelp logo

htmlua's Introduction

htmlua

Lua's C module for parsing html text, wrapper of liigo::HtmlParser

LUA的HTML解析库,C模块,封装自C++的库 liigo::HtmlParser

###〇、基本概念

本HTML解析器把HTML文本解析为一组有序的节点(Node)。各节点分为不同的类型,记录了不同的信息。 节点的类型有:开始标签(如<a href="...">)、结束标签(如</a>)、文本、注释等。 开始标签和结束标签都有一个标签名称(tagname,如上例的"a"),相应的有一个标签类型(tagtype,用整数标识标签)。 开始标签节点往往有一系列属性(Attributes,如前例中的"href")。

本文第四节将专门介绍节点类型和标签类型。更多信息请参考我CSDN博客上的文章

###一、加载htmlua库,创建parser解析器对象

local html = require "htmlua"

该html对象(可自由命名)有以下两个函数:

html.newparser(fn1,fn2)   -- 创建解析器对象,两参数均可省略(详见下文第五节),返回parser
html.deleteparser(parser) -- 删除解析器对象,参数为parser,无返回值

该html对象还有一个自动创建好的 parser 成员,可供直接使用,无需显式创建和删除。

###二、parser解析器对象,解析HTML文本

parser解析器有以下方法(需首先传入parser自身作为第一个参数):

parser:parse(html,[parseAttr]) -- 解析HTML文本,参数1是HTML文本,参数2指定是否解析节点属性(默认为true),无返回值
parser:nodecount() -- 返回解析后的节点个数
parser:node(index) -- 返回解析后的指定索引处的节点对象,参数是节点索引(>=1,<=nodecount()),返回值是node对象(索引非法时返回nil)
parser:ipairs()    -- 用于支持for循环顺序遍历节点,如:for index,node in parser:ipairs() do ...

借助于 parser:ipairs() 方法,可以用 for 循环顺序遍历 node 节点对象:

parser:parse("<html><body bg=red id=liigo>xxx<p x=123>...")
for index,node in parser:ipairs() do
	print("node:", index, node.tagname, node.text)
end

###三、node节点对象,获取节点信息

node对象有以下成员:

node.type      -- 节点类型(int),可为 htmlnode.START_TAG, htmlnode.END_TAG... 等常量值之一,详见第四节htmlnode
node.text      -- 节点文本(string)
node.tagname   -- 标签名称(string)
node.tagtype   -- 标签类型(int),可为 htmltag.A, htmltag.DIV, htmltag.IMG... 等常量值之一,详见第四节htmltag
node.attrcount -- 属性个数(int)
node.iscdata   -- 是否CDATA区块(bool)
node.isselfclosing -- 是否自结束标签(bool)(例如<br/>为自结束标签)

node对象有以下方法(需首先传入node自身作为第一个参数):

node:attr(index/name) -- 取指定属性值。如果参数是属性名(string),返回属性值(string);如果参数是属性索引(>=1,<=attrcount),返回属性名(string)和属性值(string);如果参数指定的属性不存在,返回两个nil。
node:pairs()     -- 用于支持for循环遍历属性,如 for name,value in node:pairs() do ...
node:parseattr() -- 解析节点属性,无参数无返回值,解析结果存入node对象中。如果先前已经解析过,不会重复解析。

借助于 node:pairs() 方法,可以用 for 循环遍历节点属性:

local node1 = parser:node(1)
for name,value in node1:pairs() do
	print("attr:", name, value)
end

注意,操作node的过程中需保证parser对象始终有效,且没有调用parser:parse()执行下一次解析。

###四、节点类型和标签类型

节点类型用一个整数来表示,本库已事先定义了如下节点类型常量:

htmlnode = {
	START_TAG = 1, --开始标签,如 <a href="liigo.com"> 或 <br/>
	END_TAG   = 2, --结束标签,如 </a>
	CONTENT   = 3, --内容: 介于开始标签和/或结束标签之间的普通文本
	REMARKS   = 4, --注释: <!-- -->
	UNKNOWN   = 5, --未知的节点类型
	_USER_    = 10, --用户定义的其他节点类型值应大于_USER_,以确保不与上面定义的常量值重复
}

使用方法: if(nodetype == htmlnode.START_TAG) ...

标签类型也用一个整数来表示,本库已事先定义了如下标签类型常量:

htmltag = {
	UNKNOWN = 0, --表示未经识别的标签类型,参见HtmlParser.onIdentifyHtmlTag()
	SCRIPT=1, STYLE=2, TEXTAREA=3, --出于解析需要必须识别<script>,<style>和<textarea>,内部特别处理
	--以下按标签字母顺序排列, 来源:http://www.w3.org/TR/html4/index/elements.html (HTML4)
	--还有 http://www.w3.org/TR/html5/section-index.html#elements-1 (HTML5)
	A=11, ABBR=12, ACRONYM=13, ADDRESS=14, APPLET=15, AREA=16, ARTICLE=17, ASIDE=18, AUDIO=19,
	B=20, BASE=21, BASEFONT=22, BDI=23, BDO=24, BIG=25, BLOCKQUOTE=26, BODY=27, BR=28, BUTTON=29,
	CAPTION=30, CENTER=31, CITE=32, CODE=33, COL=34, COLGROUP=35, COMMAND=36,
	DATALIST=37, DD=38, DEL=39, DETAILS=40, DFN=41, DIR=42, DIV=43, DL=44, DT=45, EM=46, EMBED=47,
	FIELDSET=48, FIGCAPTION=49, FIGURE=50, FONT=51, FOOTER=52, FORM=53, FRAME=54, FRAMESET=55,
	H1=56, H2=57, H3=58, H4=59, H5=60, H6=61, HEAD=62, HEADER=63, HGROUP=64, HR=65, HTML=66,
	I=67, IFRAME=68, IMG=69, INPUT=70, INS=71, ISINDEX=72, KBD=73, KEYGEN=74,
	LABEL=75, LEGEND=76, LI=77, LINK=78, MAP=79, MARK=80, MENU=81, META=82, METER=83, NAV=84, NOFRAMES=85, NOSCRIPT=86,
	OBJECT=87, OL=88, OPTGROUP=89, OPTION=90, P=91, PARAM=92, PRE=93, PROGRESS=94, Q=95, RP=96, RT=97, RUBY=98,
	S=99, SAMP=100, SECTION=101, SELECT=102, SMALL=103, SOURCE=104, SPAN=105, STRIKE=106, STRONG=107, SUB=108, SUMMARY=109, SUP=110,
	TABLE=111, TBODY=112, TD=113, TFOOT=114, TH=115, THEAD=116, TIME=117, TITLE=118, TR=119, TRACK=120, TT=121,
	U=122, UL=123, VAR=124, VIDEO=125, WBR=126,
	_USER_=150, --用户定义的其他标签类型值应大于_USER_,以确保不与上面定义的常量值重复
}

使用方法: if(tagtype == htmltag.DIV) ...

###五、parser解析器的回调函数

函数 html.newparser([fnOnParseAttr],[fnOnNodeReady]) 有两个可省略的参数,可接收两个函数作为回调函数,它们在解析过程中被多次调用,其原型如下:

function fnOnParseAttr(node) bool
function fnOnNodeReady(node) bool

回调函数 fnOnParseAttr 在解析到开始标签且需要解析属性时被调用。参数是当前节点对象node,返回值类型是bool。返回true表示需要解析属性,返回false表示不需要。如果此参数被省略或为nil,等价于返回true。parser:parse()参数parseAttr为false的情况下不会调用此回调函数。

回调函数 fnOnNodeReady 在解析完成每个节点后被调用,用户可在此确定是否继续解析后续节点。参数是当前节点对象node,返回值类型是bool。返回true表示继续解析,返回false表示终止解析。如果此参数被省略或为nil,等价于返回true。

本库的测试例程 test.lua 中有使用这两个回调函数的示例,基本代码如下:

local function onParseAttr(node)
	print("onParseAttr:", node.tagname, node.text)
	return (node.tagname == "2")
end

local function onNodeReady(node)
	print("onNodeReady:", node.tagname, node.text)
	return (node.tagname ~= "break")
end

local parser = html.newparser(identifyHtmlTag, onNodeReady)

htmlua's People

Contributors

liigo avatar

Watchers

James Cloos avatar Joey-Lee avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.