|
楼主 |
发表于 2016-10-7 14:27
|
显示全部楼层
本帖最后由 liu-aguang 于 2016-10-20 09:38 编辑
<三>HTML文档解析
HTML文档被转化为HTML DOM后,所有的元素都被定义为了对象.我们可以应用这些对象的属性或方法访问自己需要的内容.
<一>Document对象
Document对象就是指整个HTML文档对象, 在节点树处于顶端.它的一些方法与属性可以帮助我们访问(锁定)一个具体的元素.
1. 在VBE中声明Document有两种方法:
前期引用:(需要在VBE"工具"-"引用"-Microsoft HTML Object Library)
Dim oDom As New HTMLDocument
该语句声明一个变量oDom为Document对象.
后期引用:
Set oDom = CreateObject("HTMLFIlE")
在实践中发现前期引用与后期引用有一定的差别:
如前期引用,则不能用Write方法把网页写入;而后期引用不能识别Class(类)
2.网页文本加载, 加载有两种方式, 例:
Sub a()
Set oDom = CreateObject("htmlfile")
oDom.body.innerHTML = "<p>这是一个段落</p>"
End Sub
Sub b()
Set oDom = CreateObject("HTMLFIlE")
oDom.write "<p>这是一个段落</p>"
End Sub
讨论:
(1)过程a是把网页代码写入oDom的Body标签内.如果写入的网页有<head>,它会忽略.
(2)过程b会把整个网页写入oDom中(包括<Head>,如果有的话).
(3)两种加载方式最大不同点是:用Write方式加载,它会同时初始化或执行网页中的动态代码.而过程a则不会.
(4)多数情况下,我们采用过程a方式加载网页.
3. Document对象访问元素的方法:
(1)根据元素的ID,Name,TagName,Calss属性访问元素.
语法:
Document.getElementById("id名") 返回带有指定 ID 的元素。
Document.getElementsByName("元素name值") VBA中不支持
Document.getElementsByTagName("元素标签名") 返回包含带有指定标签名称的所有元素的节点列表(集合/节点数组)。
Document.getElementsByCalssName("元素Class名") 返回包含带有指定类名的所有元素的节点列表。'必须前期引用
(2)根据Document集合对象访问元素(过时方式,都可以用上面方法替代).
Document.all(i) '根据标签在网页中序号访问该元素.
Document.all(name) '根据标签的name属性访问元素,如果出现多个相同名字,则结果为数组;
Document.all.tags(tagName) '根据标签名来访问元素,也得到一个数组结果.
例 3.1 根据ID名访问元素内容
Sub getid()
Set oDom = CreateObject("htmlfile")
oDom.body.innerHTML = "<h1 id='myHeader'>This is a header</h1>"
MsgBox oDom.getElementById("myHeader").innerText
End Sub
讨论:
<1>本例由ID锁定元素结点<h1>,利用结点的属性innerText,获得元素<h1>文本的内容.
<2>元素节点对象属性:
innerText '返回节点元素内容文本
innerHTML '返回节点元素内容代码
nodeName '返回节点名,即标签名
nodeValue '返回节点值
nodeType '返回节点类型
例3.2 根据标签名访问元素内容
Sub getTagName()
Set oDom = CreateObject("htmlfile")
oDom.body.innerHTML = "<h1 class='myHeader'>This is a header</h1><h1>这是另一个标题</h1>"
MsgBox oDom.getElementsByTagName("h1")(0).innerText
MsgBox oDom.getElementsByTagName("h1")(1).innerText
End Sub
讨论:
1. 根据标签名访问元素, 得到的是一个数组,可以用索引法(从0开始),或遍历法读取每个值.
2. 在一个网页文档中,可能有若干的相同标签,当我们解析它们时,索引号是从0开始,并且从前彺后排序.
例3.3 根据元素的类名访问元素内容
Sub getTagName()
' 此例必须使用前期引用
Dim oDom As New HTMLDocument
oDom.body.innerHTML = "<h1 class='myHeader'>This is a header</h1><h1>这是另一个标题</h1>"
MsgBox oDom.getElementsByClassName("myHeader")(0).innerText
End Sub
例3.4 获取元素的某个属性值
Sub getAttr()
Set oDom = CreateObject("htmlfile")
Dim oDom As New HTMLDocument
oDom.body.innerHTML = "<a id='myAnchor' href='http://www.microsoft.com'>Microsoft</a>"
MsgBox oDom.getElementById("myAnchor").href
End Sub
讨论: 访问属性方法 - 元素对象.属性名
4.根据节点的方法与属性访问元素
不是所有标签都有id,name或class属性的.当我们要分离的内容正好在这样的标签中,此时可以用节点的一些方法属性,间接访问到我们需要的内容.
<1>firstChild/lastChild
前者是返回元素的第一个子节点;后者是返回最后一个子节点.
例 4.1
Sub jdTest()
Set oDom = CreateObject("htmlfile")
oDom.body.innerHTML = "<ul id='myList'><li>Coffee</li><li>Tea</li></ul>"
MsgBox oDom.getElementById("myList").FirstChild.innerText
MsgBox oDom.getElementById("myList").LastChild.innerText
End Sub
讨论: 1>本例是通过父节点来查询子节点.
2> 节点有如下属性:
innerText '返回节点元素内容文本
innerHTML '返回节点元素内容代码
nodeName '返回节点名,即标签名
nodeValue '返回节点值
nodeType '返回节点类型
<2>childNodes
返回元素子节点的 NodeList(集合).
例4.2
Sub jdTest()
Set oDom = CreateObject("htmlfile")
oDom.body.innerHTML = "<ul id='myList'><li>Coffee</li><li>Tea</li></ul>"
Set listNode = oDom.getElementById("myList").ChildNodes
MsgBox listNode.Length '获取子节点数
MsgBox listNode(0).innerHTML '索引法获取第一个子节点的内容.
End Sub
讨论: 可以用for each 或 for i遍历.
(3)parentNode
返回元素的父节点.
例 4.3
Sub pjdTest()
Set oDom = CreateObject("htmlfile")
oDom.body.innerHTML = "<ul><li>Coffee</li><li>Tea</li></ul>"
Set parNode = oDom.getElementsByTagName("li")(0).ParentNode
MsgBox parNode.nodeName
MsgBox parNode.innerText
MsgBox parNode.innerHTML
End Sub
(4)nextSibling/previousSibling
前者返回下一个同胞,后者返回前一个同胞.
例 4.4
Sub sibTest()
Dim id
Set oDom = CreateObject("htmlfile")
oDom.body.innerHTML = "<ul id='myList'><li id='item1'>Coffee</li><li id='item2'>Tea</li></ul>"
Set nexNode = oDom.getElementById("item1").NextSibling
MsgBox nexNode.id
MsgBox nexNode.innerText
Set preNode = oDom.getElementById("item2").PreviousSibling
MsgBox preNode.id
MsgBox preNode.innerText
End Sub
(5)getElementsByTagName()
前面知道Document对象具有该方法, 而其它节点对象也有该方法.
例:测试HTML文档
<div id="nav" class="nav">
<ul>
<li><a href='/newindexSpace.aspx?id=7cbf5455-d3cc-42ba-b27a-377ebd3b31fb&type=gw' target='_blank' >OA办公中心</a></li><li><a href='../ShowLv2.aspx?dis=%e6%a0%a1%e5%9b%ad%e5%9b%be%e4%b9%a6%e4%b8%ad%e5%bf%83&type=79e18d1f-ed03-4cf7-9a4f-47a282fb54a6' target='_blank' >校园图书中心</a></li><li><a href='/newindexSpace.aspx?id=96f81bd6-d833-4d74-a07c-8f85496d0c88&type=xy' target='_blank' >校园管理中心</a></li><li><a href='/admini/zp/YiRuiTe.aspx' target='_blank' >实验活动评选</a></li><li><a href='../ShowLv2.aspx?dis=%e8%bf%90%e7%bb%b4%e7%ae%a1%e7%90%86%e4%b8%ad%e5%bf%83&type=9dc96093-7912-4b15-86da-3196b4fa38c3' target='_blank' >运维管理中心</a></li>
</ul>
</div>
Sub 访问第二个a元素()
s = "<div id='nav' class='nav'><ul><li><a href='/newindexSpace.aspx?id=7cbf5455-d3cc-42ba-b27a-377ebd3b31fb&type=gw' target='_blank' >OA办公中心</a></li><li><a href='../ShowLv2.aspx?dis=%e6%a0%a1%e5%9b%ad%e5%9b%be%e4%b9%a6%e4%b8%ad%e5%bf%83&type=79e18d1f-ed03-4cf7-9a4f-47a282fb54a6' target='_blank' >校园图书中心</a></li><li><a href='/newindexSpace.aspx?id=96f81bd6-d833-4d74-a07c-8f85496d0c88&type=xy' target='_blank' >校园管理中心</a></li><li><a href='/admini/zp/YiRuiTe.aspx' target='_blank' >实验活动评选</a></li><li><a href='../ShowLv2.aspx?dis=%e8%bf%90%e7%bb%b4%e7%ae%a1%e7%90%86%e4%b8%ad%e5%bf%83&type=9dc96093-7912-4b15-86da-3196b4fa38c3' target='_blank' >运维管理中心</a></li></ul></div>"
Set oDom = CreateObject("htmlfile")
oDom.body.innerHTML = s
MsgBox oDom.getElementById("nav").getElementsByTagName("a")(1).innerText
MsgBox oDom.getElementById("nav").getElementsByTagName("a")(1).href
End Sub
讨论: 真实的网页中可能有很多的a标签, 采用该方法可以锁定id为nav的Div元素内的a标签.
(6)获取元素(或标签)的属性值
方法1: 通过节点对象与属性名用点联接获取
例4.5
Sub atTest()
Set oDom = CreateObject("htmlfile")
oDom.body.innerHTML = "<a href='/jsref/dom_obj_attributes.asp' target='_blank'>Attr 对象</a>"
Set aNode = oDom.getElementsByTagName("a")(0)
MsgBox aNode.href
MsgBox aNode.target
End Sub
方法2:应用节点的getAttribute()属性,例:
Sub atTest1()
Set oDom = CreateObject("htmlfile")
oDom.body.innerHTML = "<a href='/jsref/dom_obj_attributes.asp' target='_blank'>Attr 对象</a>"
Set aNode = oDom.getElementsByTagName("a")(0)
MsgBox aNode.getAttribute("href")
MsgBox aNode.getAttribute("target")
End Sub
5. 应用Table对象读取表数据
在HTML DOM中Table代表一个表格,它具有rows和cells两个集合对象,可通过它们读取表格内数据:
rows 返回包含表格中所有行的一个数组
cells 返回包含表格中所有单元格的一个数组。
我们先编制一个两行,每行含有两个单元格的表格:
<table id="myTable" border="1">
<tr>
<td>Row1 cell1</td>
<td>Row1 cell2</td>
</tr>
<tr>
<td>Row2 cell1</td>
<td>Row2 cell2</td>
</tr>
</table>
解析方法:
Sub atTest1()
Set oDom = CreateObject("htmlfile")
oDom.body.innerHTML = "<table id='myTable' border='1'><tr><td>Row1 cell1</td><td>Row1 cell2</td></tr><tr><td>Row2 cell1</td><td>Row2 cell2</td></tr></table>"
Set aNode = oDom.getElementById("myTable")
rn = aNode.Rows.Length '表总行数
ReDim arr(1 To rn, 1 To 2)
For Each r In aNode.Rows
i = i + 1: j = 0
For Each c In r.Cells
j = j + 1
arr(i, j) = c.innerText
Next
Next
Range("a1").Resize(rn, 2) = arr
End Sub
补充内容 (2017-7-27 20:35):
本部分中谈到根据元素的Name属性访问元素, 在VBA中不支持. 这个说法是错误的, 也就是说可以用getElementsByName()方法. |
评分
-
2
查看全部评分
-
|