【问题标题】:Selenium - NG-IF or Next Element?Selenium - NG-IF 还是 Next Element?
【发布时间】:2019-03-27 02:58:05
【问题描述】:

我正在使用 Selenium 为内部 Intranet 开发 VBA 网络抓取工具,但我无法提取几块。我在使用 CSS 访问大部分数据方面运气不错,但也遇到过几种情况,其中类是常用的,并且某些元素的位置可能会有所不同。

<div class="col-xs-12 col-sm-4 header-section header-list">

<li>
    <i class="hire-icon-contactcard-outline header-list-icon"></i>
    <span class="modal-link ng-binding" data-ng-click="createContactCardModal()">View full contact card</span>
</li>

<li>
    <i class="hire-icon-email-outline header-list-icon"></i>
    <!-- ngIf: !candidate.hasEmailAddress() -->
    <!-- ngIf: candidate.hasEmailAddress() -->
    <a href="mailto:testemail@gmail.com" ng-if="candidate.hasEmailAddress()" class="ng-binding ng-scope">testemail@gmail.com</a>
    <!-- end ngIf: candidate.hasEmailAddress() -->
</li>

<li>
    <i class="hire-icon-phone-solid header-list-icon"></i>
    <!-- ngIf: !candidate.hasPhoneNumber() -->
    <!-- ngIf: candidate.hasPhoneNumber() -->
    <span ng-if="candidate.hasPhoneNumber()" class="ng-binding ng-scope">123-456-7898</span>
    <!-- end ngIf: candidate.hasPhoneNumber() -->
</li>

我一直在尝试以下各种方法,感觉有点接近,但知道我的代码可能已关闭。

CandidateEmail = bot.FindElementByCss("[class$='hire-icon-email-outline header-list-icon']/following-sibling::[@class='ng-binding ng-scope'])")

CandidateEmail = bot.FindElementByXPath("//i[@class='hire-icon-email-outline header-list-icon']/following-sibling::a[@class='ng-binding ng-scope'])")

知道我可能缺少什么吗?此外,是否可以简单地让 selenium 选择 ngIf 元素 - 例如

提前感谢您的时间和洞察力!非常感谢!

【问题讨论】:

    标签: excel vba selenium web-scraping


    【解决方案1】:

    考虑使用 css 属性 = 值选择器与 ^ 开头的运算符组合,以通过其 href 值定位电子邮件元素。

    bot.FindElementByCss("[href^=mailto]")
    

    如果需要,您可以进一步指定添加一个额外的属性选择器(或者实际上将第二个替换为上面的第一个):

    bot.FindElementByCss("[href^=mailto][ng-if='candidate.hasEmailAddress()']")
    

    另外,考虑一个相邻的兄弟组合器,您可以在电子邮件图标之后指定 a 标签。

    bot.FindElementByCss(".hire-icon-email-outline ~ a")
    

    这是子字符串匹配的一种潜在应用

    Dim dict As Object, key As Variant
    Set dict = CreateObject("Scripting.Dictionary")
    dict.Add "hasEmailAddress", vbNullString
    dict.Add "hasPhoneNumber", vbNullString
    
    For Each key In dict.keys
        On Error Resume Next
        dict(key) = bot.FindElementByCss("[ng-if*=" & key & "]").Text 'assuming no illegal characters in string
        Debug.Print key, bot.FindElementByCss("[ng-if*=" & key & "]").Text
        On Error GoTo 0
    Next
    

    【讨论】:

    • 感谢您的回复 - 我宁愿不使用特定的东西来查找 href,因为这是整个网站的常见挑战,而不仅仅是特定于电子邮件地址。例如,即使尝试在给定代码中查找电话号码,我也必须遵循相同的方法。我尝试使用相邻的兄弟组合器,但它不起作用。
    • 它们具有相似的结构,因此您可以列出子字符串并在循环期间将它们连接起来
    • 您是否尝试过编辑,因为 css 选择器应该是更快的方法。
    【解决方案2】:

    在 css 选择器中,您似乎在其中混合了 XPath 的语法;并且这两个示例都可能会被您的班级名称中的空格绊倒。我会使用:

    CandidateEmail = bot.FindElementByCss(".hire-icon-email-outline.header-list-icon")
    

    开头的点告诉它寻找指定类名的元素,你需要用点替换类中的空格,否则会被认为是两个类。

    哦,我刚刚注意到您正在寻找应该能够通过以下内容定位的“a”元素(如果这是整个 HTML):

    CandidateEmail = bot.FindElementByCss("a.ng-binding.ng-scope")
    

    或者(同样,如果您发布的是整个 HTML),那里只有一个“a”元素,这意味着以下应该可以工作:

    CandidateEmail = bot.FindElementByCss("a")
    

    【讨论】:

    • 感谢您的回复,适用于其他选择器的格式是 CandidateName = bot.FindElementByCss("[class$='candidate-name ng-binding']").Attribute("innerText") 仅使用 ng-binding.ng-scope 不起作用,因为它在 html 的其余部分中普遍使用。这只是完整代码中的一小段代码。第一个例子不起作用。我尝试将 .Attribute("innerText") 添加到末尾,但这也没有改变任何东西。
    • 好吧,除非我看到完整的 HTML,否则我将很难指定任何唯一的选择器。如果您发布所有 html,我相信您会得到答案。
    【解决方案3】:

    显然我拥有了我需要的一切,只是需要更多地玩它。

    能够通过以下方式使其正常工作

    CandidateEmail = bot.FindElementByXPath("//a[@ng-if='candidate.hasEmailAddress()']").Attribute("innerText")
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-02-05
      • 2019-01-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-25
      • 2020-07-05
      相关资源
      最近更新 更多