Селен - NG-IF или следующий элемент? - PullRequest
1 голос
/ 27 марта 2019

Я разрабатываю веб-скребок VBA для внутренней интрасети, используя Selenium, и застрял в извлечении нескольких частей.Мне повезло в доступе к большинству данных с использованием 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'])")

Есть идеи, что я могу упустить?Кроме того, можно ли просто селеном выбрать элемент ngIf, например

Заранее спасибо за ваше время и понимание!Это очень ценится!

Ответы [ 3 ]

0 голосов
/ 27 марта 2019

Попробуйте использовать комбинацию селектора атрибута = значение css с ^, начинающимся с оператора, для нацеливания на элемент электронной почты по его значению href.

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

Вы могли бы дополнительно указать, если необходимо, добавление дополнительного селектора атрибута (или, фактически, сброс второго для первого в приведенном выше):

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

Также рассмотрим соседний братский комбинатор, в котором вы указываете тег после значка электронной почты.

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
0 голосов
/ 28 марта 2019

Видимо, у меня было все, что мне нужно, просто нужно было больше с ним играть.

Был в состоянии заставить это работать через следующее

CandidateEmail = bot.FindElementByXPath("//a[@ng-if='candidate.hasEmailAddress()']").Attribute("innerText")
0 голосов
/ 27 марта 2019

В селекторе 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")
...