Почему функция во вложенном условном выражении XPATH вызывает ошибку? - PullRequest
1 голос
/ 17 июня 2020

Это вопрос об ошибке «xpath expression is invalid», полученной в результате вызова webDrv.find_elements_by_xpath ().

Background

При поиске на сайте вакансий для элементов, содержащих текст названия целевой должности, например, «scrum master» (нормализованный до lower ()), найденный в таком элементе, как

<a href="/jobs/view/1836192833/">
    Scrum MASTER
</a>

Selenium- Python query ...

aJobTitle = getNormalJobTitle(...) # to match "scrum master" with "Scrum Master" "SCRUM Master" etcA s = '// *[contains(translate(text(),"ABCDEFGHIJKLMNOPURSTUWXYZ", "abcdefghijklmnopurstuwxyz"), "' + aJobTitle + '")]' jobNodes = webDrv.find_elements_by_xpath(s)

отлично работает. Все элементы "Scrum MASTER", "Scrum Master," Scrum master, "et c. Возвращены.

Однако, когда веб-сайт - по каким-либо причинам - включает другие элементы , например,

<a href="/jobs/view/1836192833/"> Scrum Master <!----> </a>

приведенный выше запрос ничего не находит.

Использование другой формы xpath - и работа без нормализации lower () ...

s = "//*[text()[contains(.,'" + "Scrum MASTER" + "')]]" jobNodes = webDrv.find_elements_by_xpath(s)

работает отлично. Все и только элементы «Scrum MASTER» возвращены (но не «Scrum Master» и c., Конечно)

Моя проблема

Однако, когда я пытаюсь выполнить поиск, используя нормализованное название должности в нижнем регистре, заменяя вызов text() вызовом translate(text(),,) ...

aJobTitle = getNormalJobTitle(...) # "scrum master" s = "//*[translate(text(),'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')[contains(.,'" + aJobTitle + "')]]"

Меня угостили

Exception has occurred: InvalidSelectorException Message: Given xpath expression "//*[translate(tex(),'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')[contains(.,'scrum master')]]" is invalid: [Exception... "<no message>" nsresult: "0x80600008 (<unknown>)" location: "JS frame :: chrome://marionette/content/element.js :: element.findByXPathAll :: line 410" data: no] File "C:myfile.py JS.py", line 41, in <module> jn = liJobsElement.find_elements_by_xpath(s)

Итак, наконец ...

1) Почему добавление функции вызывает ошибку? 2) Как мне добиться такой нормализации, чтобы я мог найти все регистры, например, название должности?

1 Ответ

0 голосов
/ 18 июня 2020

Вы пишете: translate(text(),'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')[

Вы не можете использовать предикат со строкой (то есть: вывод функции translate). Вот почему ваш XPath недействителен. Что можно проверить, так это элементы, атрибуты и text() узлы.

Что касается вашей проблемы, то ваш первый XPath мне нравится. Но некоторые движки XPath не считают это действительным. Рабочий XPath может быть:

С функцией normalize-space (мы удаляем contains функцию):

//*[translate(normalize-space(),"ABCDEFGHIJKLMNOPQRSTUVWXYZ","abcdefghijklmnopqrstuvwxyz")="scrum master"]

С контекстным элементом . (вместо проблемного c text()), но мы должны указать имя элемента (a) или добавить предикат (без дочернего элемента):

//a[contains(translate(.,"ABCDEFGHIJKLMNOPURSTUWXYZ", "abcdefghijklmnopurstuwxyz"),"scrum master")]

//*[contains(translate(.,"ABCDEFGHIJKLMNOPURSTUWXYZ", "abcdefghijklmnopurstuwxyz"),"scrum master")][count(./*)=0]

Итак, чтобы подвести итог, вы можете использовать что-то вроде:

s = '//*[translate(normalize-space(),"ABCDEFGHIJKLMNOPQRSTUVWXYZ","abcdefghijklmnopqrstuvwxyz")="%s"]'%str(aJobTitle)
jobNodes = webDrv.find_elements_by_xpath(s)

или

s = '//a[contains(translate(.,"ABCDEFGHIJKLMNOPURSTUWXYZ", "abcdefghijklmnopurstuwxyz"),"%s")]'%str(aJobTitle)
jobNodes = webDrv.find_elements_by_xpath(s)

или

s = '//*[contains(translate(.,"ABCDEFGHIJKLMNOPURSTUWXYZ", "abcdefghijklmnopurstuwxyz"),"%s")][count(./*)=0]'%str(aJobTitle)
jobNodes = webDrv.find_elements_by_xpath(s)
...