webbrowser获取动态网页元素

时间:2022-11-26 11:57:42

写第一个博客前先啰嗦介绍下我本人:我其实是个硬件工程师,只是喜欢编程,觉得程序可以大大释放劳动力,所以偶尔会写些小程序,解决日常工作中的小问题,而我写的小程序,都是自动化方向的多(例如本次要实现的自动填表),而且对编程中遇到的问题,会不懈地寻找答案,也因为不是专业程序员,所以一些在大家看来很简单的问题,对我来说就变得不简单。

 

通过webbrowser获取静态网页元素比较容易,而要获取动态网页元素就不太容易了,在网上搜索了很久,看了很多文章,最后终于找到答案。

这篇文章:《[参考资料]如何用Python,C#等语言去实现抓取静态网页+抓取动态网页+模拟登陆网站》  让我学会了用浏览器中的开发人员工具(IE9的F12和Chrome的Ctrl+Shift+I)-网页分析的利器,从而坚定地知道,动态网页元素是一定可以获取的,只是还未找到方法而已。

其实这篇文章:《C# WebBrowser 获取被点击的对像》  里面也提到了解决办法,只是我漏掉了而已。

直到看了这篇文章:《如何获取 WebBrowser.Document 中某命名空间中的元素?》  才真正解决了我要解决的问题,因为里面的网页例子与我要分析的网页一模一样。

webbrowser获取动态网页元素

技术的关键点是这行代码:webBrowser1.Document.Window.Frames("frm_xxx").Document.Forms(0).InnerHtml

而不是像这个帖子:《请教高手,关于WebBrowser控制Jsp网页元素和获取元素的数据,在线等..》  里5楼说的:WebBrowser1.Document.frames.Item(frameindex).Document.documentElement.outerHTML 

 

根据关键代码,我写了个递归调用函数,用来查找动态网页元素,该函数的缺点是,遇到同一层次的,没有Id、InnerText、Name、title、classname、value,或这些属性值一样的网页元素时,只能返回第一个匹配的网页元素。解决的办法是找到同一层的网页元素后再通过.Parent  、NextSibling、Children来访问。

Function FindHtmlElement(ByVal FindText As String, ByVal doc As HtmlDocument, ByVal cTagName As String, ByVal cGetAttribute As String, Optional ByVal StrictMatching As Boolean = False) As HtmlElement
        'cTagName:检索具有指定 html 标记的元素,标记需要输入完整的,缺省时查找所有。
        '例如:<input class="button" type="submit" value=提交 style="cursor:hand">,不能只输入"i",需要输入"input"
        'cGetAttribute :比较的属性类型,取值为:Id、InnerText、Name、title、classname、value、
        'Id、InnerText可以通过GetAttribute获取,也可以通过HtmlElement.Id、HtmlElement.InnerText获取,所以代码简化为用GetAttribute获取。
        'doc:Webbrowser1.Document
        'GetAttribute("classname")   '例如显示class="commonTable"的值commonTable
        'StrictMatching:True严格匹配FindText

        Dim i, k As Integer

        FindHtmlElement = Nothing

        For i = 0 To doc.All.Count - 1
            If InStr(doc.All.Item(i).GetAttribute(cGetAttribute), FindText) > 0 _
                And (Not StrictMatching Or InStr(FindText, doc.All.Item(i).GetAttribute(cGetAttribute)) > 0) And (cTagName = "" Or LCase(cTagName) = LCase(doc.All.Item(i).TagName)) Then
                FindHtmlElement = doc.All.Item(i)
                Exit Function
            End If
        Next

        For k = 0 To doc.Window.Frames.Count - 1
            For i = 0 To doc.Window.Frames.Item(k).Document.All.Count - 1
                If InStr(doc.Window.Frames.Item(k).Document.All.Item(i).GetAttribute(cGetAttribute), FindText) > 0 And (Not StrictMatching Or InStr(FindText, doc.Window.Frames.Item(k).Document.All.Item(i).GetAttribute(cGetAttribute)) > 0) And (cTagName = "" Or LCase(cTagName) = LCase(doc.Window.Frames.Item(k).Document.All.Item(i).TagName)) Then
                    FindHtmlElement = doc.Window.Frames.Item(k).Document.All.Item(i)
                    Exit Function
                End If
            Next

            '递归调用
            If FindHtmlElement Is Nothing Then
                FindHtmlElement = FindHtmlElement(FindText, doc.Window.Frames.Item(k).Document, cTagName, cGetAttribute, StrictMatching)
            End If
        Next

    End Function