【问题标题】:Is there a possibility to address elements on a website which have no ID?是否有可能解决网站上没有 ID 的元素?
【发布时间】:2018-02-15 17:41:23
【问题描述】:

在带有网络浏览器的 Vb.net 中,我通常使用GetElementById 来寻址例如按钮。我知道有GetElementFromPoint,我觉得非常费力。

当 ID 未知时,有没有更好、更简单的方法?

【问题讨论】:

    标签: vb.net webbrowser-control


    【解决方案1】:

    您将需要使用某种类型的选择器。

    GetElementByID 方法效果最好,因为如果 HTML 文件格式正确,那么应该只有一个元素具有该唯一 ID。

    GetElementFromPoint 会根据文档的 X,Y 坐标返回一个元素,这最好用在文档的 Click 事件中。

    GetElementByTagName 名称将返回一个元素集合,如果您知道元素的标记类型(例如 <button>...</button><p>...</p>),则该名称将起作用。为了帮助缩小您想要的元素,您需要遍历返回的集合,并比较元素的属性(如果您知道它们各自的值)或通过 InnerHTML 属性比较元素的文本。

    最后一个也是最不有效的方法是All 属性,它返回文档中的每个元素。这样做效果最差的原因是因为至少使用 GetElementByTagName,您可以根据标签的名称缩小集合范围。

    但是,我们假设您有以下标记:

    <body>
      <p>Look at my super complex HTML markup.</p>
      <button>Click Me</button>
      <button>No, click me!</button>
    </body>

    然后,您可以使用以下命令获取显示“点击我”的按钮标签:

    Dim click_me As HtmlElement = WebBrowser1.Document.GetElementByTagName("button").SingleOrDefault(Function(e) e.InnerHtml = "Click Me")
    

    【讨论】:

    • 非常感谢您的详细解答。特别是最后一部分对我来说非常很有用。
    【解决方案2】:

    看到这个问题时不时被问到,我会看看我是否不能一劳永逸地解决这个问题。以下是有关如何查找没有 ID 的元素的更详尽指南:

    - 基础知识-

    您可以使用许多内置属性和方法来识别元素。最常见的包括:

    • HtmlElement.GetElementsByTagName()

      方法。返回文档/元素中具有指定 HTML 标记的所有元素的集合。这既可以在 HtmlElement 上调用,也可以在 HtmlDocument 本身上调用。

    • HtmlElement.GetAttribute()

      方法。返回指定HtmlElement 上特定属性的值。

    • HtmlElement.InnerHtml

      财产。返回位于指定元素内的所有 HTML 代码(但不返回元素本身的代码)。

    • HtmlElement.InnerText

      财产。返回位于指定元素内的所有文本(从 HTML 代码中删除)。

    • HtmlElement.OuterHtml

      财产。返回位于指定元素内的 HTML 代码,包括元素本身的代码。

    这些方法和属性都可以以不同的方式用于标识元素,如下面的示例所示。

    注意:我省略了HtmlElement.OuterText,因为它的行为有点奇怪,而且我不能 100% 确定它的实际作用。


    - 查找没有 ID 的元素的示例 -

    以下是一组示例,说明如何使用前面提到的方法和属性来查找要查找的元素。


    通过类(-name)查找元素

    要根据其class 属性查找和元素,您必须迭代所有元素并检查每个元素上的GetAttribute("className")。如果您事先知道元素类型(标签名称),则可以通过首先使用HtmlDocument.GetElementsByTagName() 而不是HtmlDocument.All 获取所有元素的集合该类型来缩小搜索范围。

    HTML 代码:

    <div class="header">
        <div id="title" class="centerHelper">
            <img id="logo" src="img/logo.png"/>
        </div>
        <p class="headerContent">
            Hello World!
        </p>
    </div>
    

    要定位的元素:

    <p class="headerContent">
    

    VB.NET 代码:

    'Iterate all elements.
    For Each Element As HtmlElement In WebBrowser1.Document.All
        If Element.GetAttribute("className") = "headerContent" Then
            'Found. Do something with 'Element'...
            Exit For 'Stop looping.
        End If
    Next
    


    根据属性查找位于另一个元素内的元素(带有 ID)

    为了根据其中一个属性找到子元素,子元素位于父元素(具有 ID)内,您只需通过其 ID 获取父元素,然后迭代其所有子元素。

    HTML 代码:

    <select id="items" class="itemsList">
        <option value="2">Apple</option>
        <option value="3">Orange</option>
        <option value="5">Banana</option>
    </select>
    

    要定位的元素:

    <option value="5">Banana</option>
    

    VB.NET 代码:

    'Iterate all children of the element with ID "items".
    For Each Element As HtmlElement In WebBrowser1.Document.GetElementByID("items").Children
        If Element.getAttribute("value") = "5" Then
            'Found. Do something with 'Element'...
            Exit For 'Stop looping.
        End If
    Next
    


    根据属性查找位于另一个元素内的元素(无 ID)

    要根据其中一个属性查找子元素,其中子元素位于父元素内(没有有 ID),您首先需要创建一个寻找 parent 元素的外部循环。然后,找到后,您就可以开始迭代孩子了。

    HTML 代码:

    <select class="itemsList">
        <option value="2">Apple</option>
        <option value="3">Orange</option>
        <option value="5">Banana</option>
    </select>
    

    要定位的元素:

    <option value="5">Banana</option>
    

    VB.NET 代码:

    'Variable keeping track of whether we found the element we're looking for or not.
    Dim ElementFound As Boolean = False
    
    'Outer loop, looking for the parent object (<select class="itemsList">).
    For Each Element As HtmlElement In WebBrowser1.Document.GetElementsByTagName("select") 'Iterate all <select> tags. You can use Document.All here as well.
        If Element.getAttribute("className") = "itemsList" Then
    
            'Parent found.
            'Inner loop, looking for the child element we want (<option value="5">Banana</option>).
            For Each OptionElement As HtmlElement In Element.GetElementsByTagName("option")
                If OptionElement.GetAttribute("value") = "5" Then
                    'Found. Do something with 'OptionElement'...
    
                    ElementFound = True
                    Exit For 'Exit the inner loop.
                End If
            Next
    
            'Exit the outer loop if we found the element we're looking for.
            If ElementFound Then Exit For
    
        End If
    Next
    


    根据 InnerText 查找元素

    在某些情况下,您要定位的元素没有任何属性,或者与网站上的许多其他元素过于相似。在这种情况下,如果其内容始终相同,您可以通过其InnerTextInnerHtml 属性来识别它。

    HTML 代码:

    <h1>Important information</h1>
    <p>Please read this information through <b>carefully</b> before continuing.</p>
    
    <h2>Copyrighted material<h2>
    <p>All material (text, images, video, etc.) on this site are <b>copyrighted</b> to COMPANY NAME.</p>
    

    要定位的元素:

    <h2>Copyrighted material<h2>
    

    VB.NET 代码:

    For Each Element As HtmlElement In WebBrowser.Document.All
        If Element.InnerText = "Copyrighted material" Then
            'Found. Do something with 'Element'...
            Exit For 'Stop looping.
        End If
    Next
    


    根据 InnerHtml 查找元素

    根据InnerHtml 查找元素的工作方式与根据InnerText 查找的方式完全相同,除了您现在检查的字符串还包含 HTML 代码。

    HTML 代码:

    <h1>Important information</h1>
    <p>Please read this information through <b>carefully</b> before continuing.</p>
    
    <h2>Copyrighted material<h2>
    <p>All material (text, images, video, etc.) on this site are <b>copyrighted</b> to COMPANY NAME.</p>
    

    要定位的元素:

    <p>All material (text, images, video, etc.) on this site are <b>copyrighted</b> to COMPANY NAME.</p>
    

    VB.NET 代码:

    'Iterate all <p> tags.
    For Each Element As HtmlElement In WebBrowser.Document.GetElementsByTagName("p")
        If Element.InnerHtml.Contains("<b>copyrighted</b>") Then
            'Found. Do something with 'Element'...
            Exit For 'Stop looping.
        End If
    Next
    

    【讨论】:

    • 这确实是一个广泛的指南。非常感谢。谢谢!
    • @Cyrill :很高兴我能帮上忙!我之前已经回答了很多此类问题(而且解决方案通常相当简单),所以我决定做一些我可以在未来参考的全方位解决方案。 :)
    猜你喜欢
    • 2011-02-04
    • 1970-01-01
    • 2021-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-08
    • 1970-01-01
    • 2015-08-04
    相关资源
    最近更新 更多