Есть ли какой-либо метод (не нашел в API) или решение, чтобы щелкнуть элемент с текстом?
Например, у меня есть html:
<div class="elements">
<button>Button text</button>
<a href=#>Href text</a>
<div>Div text</div>
</div>
И я хочу щелкнуть элемент, в который заключен текст (нажмите кнопку внутри .elements), например:
Page.click('Button text', '.elements')
Ответы:
Топовой ответ на tokland работает только на текстовых узлах , а не на узлах с другими элементами внутри.
Короткий ответ
Это выражение XPath будет запрашивать кнопку, содержащую текст «Текст кнопки»:
const [button] = await page.$x("//button[contains(., 'Button text')]"); if (button) { await button.click(); }
Чтобы также уважать
<div class="elements">
окружение кнопок, используйте следующий код:const [button] = await page.$x("//div[@class='elements']/button[contains(., 'Button text')]");
Объяснение
Чтобы объяснить, почему использование текстового узла (
text()
) в некоторых случаях неправильно, давайте рассмотрим пример:<div> <button>Start End</button> <button>Start <em>Middle</em> End</button> </div>
Для начала проверим результаты при использовании
contains(text(), 'Text')
://button[contains(text(), 'Start')]
вернет оба двух узла (как и ожидалось)//button[contains(text(), 'End')]
вернет только один узел (первый), так какtext()
возвращает список с двумя текстами (Start
иEnd
), ноcontains
проверит только первый//button[contains(text(), 'Middle')]
не будет возвращать не результаты,text()
не включает в себя текст дочерних узловВот выражения XPath для
contains(., 'Text')
, которые работают с самим элементом, включая его дочерние узлы://button[contains(., 'Start')]
вернет обе две кнопки//button[contains(., 'End')]
снова вернет обе две кнопки//button[contains(., 'Middle')]
вернет один (последняя кнопка)Поэтому в большинстве случаев имеет смысл использовать
.
вместоtext()
выражения XPath.источник
//*[...]
.Вы можете использовать селектор XPath со страницей. $ X (выражение) :
Ознакомьтесь с
clickByText
этой сутью для полного примера. Он заботится об экранировании кавычек, что немного сложно с выражениями XPath.источник
//a[contains
на,//*[contains
чтобы выбрать любой элемент, а не толькоa
элемент anchor ( ).Вы также можете использовать
page.evaluate()
для щелчка элементы, полученные изdocument.querySelectorAll()
отфильтрованных по текстовому содержимому:await page.evaluate(() => { [...document.querySelectorAll('.elements button')].find(element => element.textContent === 'Button text').click(); });
В качестве альтернативы вы можете использовать,
page.evaluate()
чтобы щелкнуть элемент на основе его текстового содержимого, используяdocument.evaluate()
и соответствующее выражение XPath:await page.evaluate(() => { const xpath = '//*[@class="elements"]//button[contains(text(), "Button text")]'; const result = document.evaluate(xpath, document, null, XPathResult.ANY_TYPE, null); result.iterateNext().click(); });
источник
сделали быстрое решение, чтобы иметь возможность использовать расширенные селекторы CSS, такие как ": contains (text)"
поэтому с помощью этой библиотеки вы можете просто
источник
Вот мое решение:
источник
Решение
источник
Нет поддерживаемого синтаксиса селектора css для текстового селектора или опции комбинатора, моя работа для этого будет:
источник
Есть много предложений,
contains
но я не вижу мотивации для этой неточности с учетом варианта использования OP, который, судя по всему, является точным совпадением с целевой строкой"Button text"
и элементом<button>Button text</button>
.Я бы предпочел использовать более точный
[text()="Button text"]
, чтобы избежать ложного срабатывания, когда кнопка, скажем<button>Button text and more stuff</button>
,:Это предполагает противоположный сценарий этого ответа, который пытается быть как можно более снисходительным.
Во многих ответах также пропущено требование
.elements
родительского класса.источник
Мне пришлось:
await this.page.$eval(this.menuSelector, elem => elem.click());
источник