ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 Excel Home精品图文教程库
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
300集Office 2010微视频教程 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
查看: 5928|回复: 6

[求助] MSXML2.DOMDocument 可分析HTML?

[复制链接]

TA的精华主题

TA的得分主题

发表于 2015-10-2 17:06 | 显示全部楼层 |阅读模式
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
本帖最后由 lolmuta 于 2015-10-2 17:08 编辑

chrome web viewer 竟然有提供网页资料的Xpath....只要对想抓的资料点个右键就可显示,实在是太方便了…(因为一直找不到方便的方式)
且照理说,HTML 也不过就是XML的结构才对。
要是可以成功的被xml读取,就可以用这自带出来的xpath方便的抓取想要的资料。


vba 分析xml  就想到  CreateObject("MSXML2.DOMDocument")
test代码 引用Microsoft XML,6.0
可知道不合规定的xml 在loadxml时,就会传回false。

  1. Sub Example()
  2.     Dim XMLDoc As MSXML2.DOMDocument
  3.     Set XMLDoc = New MSXML2.DOMDocument 'Set XMLDOC = CreateObject("MSXML2.DOMDocument")
  4.     strText_OK = "<a><b>1</b><c>2</c></a>" 'ok xml will show 1
  5.     If Not XMLDoc.LoadXML(strText_OK) Then
  6.         Stop
  7.     End If
  8.     Set b = XMLDoc.SelectSingleNode("/a/b")
  9.     Debug.Print b.Text '1
  10.    
  11.     strText_Bad = "<a><b>1</b><c>2</c></a>1" 'error xml will cause loadxml false
  12.    
  13.     If Not XMLDoc.LoadXML(strText_Bad) Then
  14.         Stop
  15.     End If
  16.     Set b = XMLDoc.SelectSingleNode("/a/b")
  17.     Debug.Print b.Text


  18. End Sub
复制代码


但是,从网路上抓下来的html 都过不了.loadxml这关,有点可惜啊…
所以,真的不能用这样的方式吗?

评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2015-10-2 17:29 | 显示全部楼层
本帖最后由 浮华、缠绕指尖 于 2015-10-2 18:52 编辑

XML和HTML还是存在不少区别的,比如开闭原则等(下面几句是百度的,大概就是XML的格式比HTML的格式要严格)

HTML的语法格式比XML宽松多了,真正XML格式的网页是XHTML,也就是下一代HTML,他的格式和XML差不多,很严谨的。

1.HTML的节点可以没末节点,你需要不停扫描<,>,/,这三个符号以检查是否漏掉末节点,并补充。

2.HTML节点还可以不规则嵌套,你需要对已读入节点进行顺序存储,或用栈的数据结构来存储,并验证其层次正确性,最终正确顺序的节点,期间还得缓存节点值,或属性值。

3.HTML不同于XML,许多HTML节点有特殊的意义,许多HTML节点比如<b>,<hr/>都需要经过特殊处理才行。

在VBA解析HTML的话一般都是使用htmlfile,当然如果想用XPATH来解析HTML格式的话,还是得先将HTML转换成XML格式,至少方法的可以用网上现成的方法或者使用自定义的类来转换
当然如果是在C#中的话,有封装好的可以使用HtmlAgilityPack,用这个的话就可以直接XPATH来解析HTML,还是很方便的

TA的精华主题

TA的得分主题

发表于 2015-10-2 18:14 | 显示全部楼层
本帖最后由 willin2000 于 2015-10-2 18:20 编辑

转帖,希望对楼主有用:

以以下代码为例:
<?xml version="1.0"?>
<memberlist>
   <member Uid="30639" timer="952" nicheng="上旋下弦月">
         <id>xmyjk</id>
         <city>厦门</city>
         <group>开心队</group>
   </member>
   <member Uid="56305" timer="529">
        <id>xyf2210</id>
        <city>浙江</city>
        <group>开心队</group>
   </member>
   <member Uid="33175" timer="3398">
         <id>海洋之星</id>
         <touxian>ET高级认证讲师</touxian>
         <city>西安</city>
         <group>腾龙队</group>
   </member>
   <member Uid="41613" timer="3122">
        <id>Zaezhong</id>
        <touxian>ET认证讲师</touxian>
        <city>未知</city>
        <group>腾龙队</group>
   </member>
   <member Uid="85249" timer="481">
         <id>Rongson_Chart</id>
         <city>未知</city>
         <group>A.C.E战队</group>
   </member>
   <member Uid="15819" timer="1279">
        <id>無心</id>
        <touxian>ET认证讲师</touxian>
        <city>未知</city>
        <group>A.C.E战队</group>
   </member>
</memberlist>

节点树的图形如下:
   1.png

    如图,memberlist就是根节点,member元素就是它的子节点,层层递推。另外,属性节点,和文本节点也是相关元素节点的子节点。通过这个节点树,我们可以运用xml dom访问所有的节点,甚至可以修改或删除它们,以及创建新元素。

    EXCEL VBA中,我们也可以用多种方式去解析xml文档,这里仅仅介绍用xmldom对象去解析。我们仅仅用以下几行代码,即可加载xml文档到xmldom对象中:

  1. Sub test1()
  2.     Dim XmlDom, i As Integer
  3.    
  4.     Set XmlDom = CreateObject("Microsoft.XMLDOM") '创建xmldom对象
  5.     XmlDom.async = False '设置不允许异步处理
  6.     XmlDom.Load 地址 '加载xml文档
  7. End Sub
复制代码


加载完毕后,我们怎么去查找我们需要的节点呢?我总结了一下,主要有以下两种:
  
  (1)使用经典的DOM-属性和方法
   
    经典方法:
      .getElementsByTagName(name) - 获取带有指定标签名称的所有元素
      .getNamedItem(name) – 仅用于获取指定名称的属性节点
      .getAttribute(name) - 获取指定名称的属性节点的值
      .getAttributeNode(name) – 获取指定名称的属性节点
   
    经典属性:
      .parentNode -父节点
      .childNodes -子节点
      .firstChild – 第一个节点
      .lastChild – 最后一个节点
      .attributes -属性节点
      .nodeValue – 文本节点的文本值或属性节点的属性值
      .Text 元素节点中包含的文本

  1. Sub test1()
  2.     Dim XmlDom, i As Integer, XmlNodes, xmlnd
  3.    
  4.     Set XmlDom = CreateObject("Microsoft.XMLDOM") '创建xmldom对象
  5.     XmlDom.async = False '设置不允许异步处理
  6.     XmlDom.Load ThisWorkbook.Path & "\1.xml" '载入xml文档
  7.     Set XmlNodes = XmlDom.getElementsByTagName("id") '查找所有ID元素节点
  8.     Debug.Print XmlNodes.Length '看看获取了多少个ID元素
  9.     Debug.Print XmlNodes(0).childnodes(0).nodevalue '获取xmyjk节点文本
  10.     Debug.Print XmlNodes(0).Text '获取xmyjk节点文本第二种方法
  11.     Debug.Print XmlDom.getElementsByTagName("member")(0).Attributes.getnameditem("timer").nodevalue '获取属性第一种方法
  12.     Debug.Print XmlDom.getElementsByTagName("member")(0).getAttribute("timer") ''获取属性第2种方法
  13.     Debug.Print XmlDom.getElementsByTagName("member")(0).getAttributeNode("timer").nodevalue ''获取属性第3种方法
  14.     For Each xmlnd In XmlNodes '历遍
  15.        Debug.Print xmlnd.Text
  16.     Next
  17. End Sub
复制代码

特别注意XmlNodes(0).childnodes(0).nodevalue这句,XmlDom.getElementsByTagName("id")获得的xmlnodes是,xml文档的所有的id的节点列表,那第一个id的节点就是包含xmyjk这个文本的id节点,这个id节点的第一个子节点就是xmyjk这个文本节点,这个文本节点的nodevalue就是xmyjk。
   
    那.text指的就是,元素节点里面包含的文本,因此可以直接跟在元素节点后面使用。得出的结果一样是xmyjk。
   
    元素节点下属的属性节点列表,可以用attributes去获取,再用.getnameditem方法去获取相应名称的属性节点,而后取值。也可以直接使用. getAttribute获取属性,或者也可以直接使用.getAttributeNode去获取属性节点再用nodevalue取值。
   
    最后,节点也是可以用FOR EACH去枚举历遍的,和VBA里面的对象历遍都是一样的。

(2)运用xpath与selectNodes()/selectSingleNode()结合
   
    XPath 是一门在 XML 文档中查找信息的语言,它使用路径表达式在 XML 文档中进行导航,类似我们的文件系统的路径表达式。XPATH选取节点的路径表达式的语法(引用了W3SCHOOL的图片表达):
  
   
    /和我们的文件路径很像,例如:memberlist/member。//就表示在所有路径中查找,例如//id就表示查找所有的id元素节点。
   
    另外,就如SQL的WHERE查询一样,我们也可以设定我们的查询条件,可以用中括号[]来书写条件。例如:memberlist/member[last()-2]这样查找member节点列表的倒数第3个member节点。

    @是专门用来查找属性节点的,例如,用来查找所有timer的属性节点,就用//@timer表示。@一样也可以在[]内使用,例如: //member[@nicheng]可以用于查找,拥有nicheng属性的member节点。
   
    甚至,我们还可以使用node()(匹配任何节点),*(匹配任何元素节点),text()(匹配任何文本节点),@*(匹配任何属性节点)这样的模糊或者类型匹配查询。
   
    最后,我们还可以使用“|”去使用多路径查找。在判断条件里面,我们还可以运用and 或者 or 或者!=等等运算符。案例请看下面的代码。

  1. Sub test2()
  2.     Dim XmlDom, i As Integer, XmlNodes, xmlnd
  3.    
  4.     Set XmlDom = CreateObject("Microsoft.XMLDOM") '创建xmldom对象
  5.     XmlDom.async = False '设置不允许异步处理
  6.     XmlDom.Load ThisWorkbook.Path & "\1.xml" '载入xml文档
  7.     Set XmlNodes = XmlDom.SelectNodes("memberlist/member") '获取所有的member元素节点
  8.     Debug.Print XmlNodes(0).Text '输出第一个member节点的文本
  9.     Set XmlNodes = XmlDom.SelectNodes("//id") '获取所有的id元素节点
  10.     Debug.Print XmlNodes(0).Text '输出第一个id节点的文本
  11.     Set XmlNodes = XmlDom.SelectNodes("//@timer") '获取所有的timer属性节点
  12.     Debug.Print XmlNodes(0).Value '输出第一个timer属性节点的值
  13.     Set XmlNodes = XmlDom.SelectNodes("//member[@nicheng]") '获取拥有nicheng属性的member节点
  14.     Debug.Print XmlNodes(0).Text '输出匹配的第一个节点的文本
  15.     Set XmlNodes = XmlDom.SelectNodes("//member[@timer>1000]/id") '获取拥有timer属性大于1000的member节点的id元素
  16.     Debug.Print XmlNodes(0).Text '输出匹配的第一个节点的文本
  17.     Set XmlNodes = XmlDom.SelectNodes("//member[city='厦门'] | //member[city='浙江']") '获取city=厦门或浙江的member节点
  18.     Debug.Print XmlNodes(1).Text '输出匹配的第二个节点的文本
  19.     Set XmlNodes = XmlDom.SelectNodes("//member[group='腾龙队' and city='未知']") '获取city=未知和组别是腾龙队的member节点
  20.     Debug.Print XmlNodes(0).Text '输出匹配的第二个节点的文本
  21.     Set XmlNodes = XmlDom.SelectSingleNode("//city[text() = '厦门']").ParentNode  '获取city元素节点的下属文本节点是厦门的member节点
  22.     Debug.Print XmlNodes.XML '输出匹配的xml代码
  23. End Sub
复制代码


评分

2

查看全部评分

TA的精华主题

TA的得分主题

发表于 2015-10-2 18:43 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
willin2000 发表于 2015-10-2 18:14
转帖,希望对楼主有用:

以以下代码为例:

挺好的资料,不过楼主的问题好像不在于XML的知识,楼主只是想知道怎么将HTML格式加载到XML中去,再使用XPATH来解析

TA的精华主题

TA的得分主题

 楼主| 发表于 2015-10-5 08:44 | 显示全部楼层
本帖最后由 lolmuta 于 2015-10-5 09:02 编辑


有些基础的资料也挻好的…

其实若是chrome有提供这个xpath速查机制,那一定有用到的地方,看来C#是有用到了但我觉得javascript应该也有用到,且vba可 叫用javascript语法。不过实在不太熟Javascript如何利用Xpath抓取网页资料...还在摸索中

TA的精华主题

TA的得分主题

发表于 2017-2-20 16:57 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
现在应该是没有xmldom这个了吧,难道是我看错了

TA的精华主题

TA的得分主题

发表于 2018-12-6 22:14 | 显示全部楼层
好东西啊!找了好久!用这个解决BOM应该很好!
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-6-25 13:35 , Processed in 0.051672 second(s), 17 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表