Aleksandr Golubovskij
¿Hay algún método o solución para hacer clic en un elemento con texto? No pude encontrar uno en la API.
Por ejemplo, tengo el siguiente HTML:
<div class="elements">
<button>Button text</button>
<a href=#>Href text</a>
<div>Div text</div>
</div>
Y quiero hacer clic en un elemento en el que se envuelve el texto (haga clic en el botón dentro .elements
), al igual que:
Page.click('Button text', '.elements')
Tomas Dondorf
Respuesta corta
Esta expresión XPath consultará un botón que contiene el texto “Texto del botón”:
const [button] = await page.$x("//button[contains(., 'Button text')]");
if (button) {
await button.click();
}
Respetar también la <div class="elements">
alrededor de los botones, use el siguiente código:
const [button] = await page.$x("//div[@class="elements"]/button[contains(., 'Button text')]");
Explicación
Para explicar por qué usar el nodo de texto (text()
) está mal en algunos casos, veamos un ejemplo:
<div>
<button>Start End</button>
<button>Start <em>Middle</em> End</button>
</div>
Primero, verifiquemos los resultados al usar contains(text(), 'Text')
:
//button[contains(text(), 'Start')]
devolverá los dos dos nodos (como se esperaba)//button[contains(text(), 'End')]
solo regresare uno nodos (el primero) comotext()
devuelve una lista con dos textos (Start
yEnd
), perocontains
solo revisare el primero//button[contains(text(), 'Middle')]
regresará No resultados comotext()
no incluye el texto de los nodos secundarios
Aquí están las expresiones XPath para contains(., 'Text')
que funciona en el propio elemento, incluidos sus nodos secundarios:
//button[contains(., 'Start')]
devolverá los dos dos botones//button[contains(., 'End')]
volverá de nuevo los dos dos botones//button[contains(., 'Middle')]
regresará uno (el último botón)
Entonces, en la mayoría de los casos, tiene más sentido usar el .
en lugar de text()
en una expresión XPath.
-
algo que funcione con todo tipo de elemento? no puedo saber si el texto está dentro de un botón, ap, un div, un lapso, etc.
– Andrea Bisello
15 de noviembre de 2019 a las 9:30
-
@AndreaBisello Puedes usar
//*[...]
en cambio.– Thomas Dondorf
15 de noviembre de 2019 a las 17:21
-
¿Podría funcionar si el ‘Texto del botón’ está en una matriz?
– usuario303749
08/04/2022 a las 14:41
-
Parece que esto no funciona:
The string '//button[contains(., "Message")]' is not a valid XPath expression.
– Jim
5 de marzo a las 20:34
tierra de tokland
Puede usar un selector XPath con página.$x(expresión):
const linkHandlers = await page.$x("//a[contains(text(), 'Some text')]");
if (linkHandlers.length > 0) {
await linkHandlers[0].click();
} else {
throw new Error("Link not found");
}
Verificar clickByText
en esto esencia para un ejemplo completo. Se encarga de escapar de las comillas, lo cual es un poco complicado con las expresiones XPath.
-
Impresionante: traté de hacerlo para otras etiquetas, pero no puedo hacerlo funcionar. (li, h1,…) ¿Cómo harías eso?
– Runa Jeppesen
9 de julio de 2018 a las 15:23
-
@RuneJeppesen Reemplazar
//a[contains
with//*[contains
to select any element, not just an anchor (a
) element.– UnixmonkeySep 16, 2020 at 15:39
Grant Miller
You can also use page.evaluate()
to click elements obtained from document.querySelectorAll()
that have been filtered by text content:
await page.evaluate(() => {
[...document.querySelectorAll('.elements button')].find(elemento => elemento.textContent === 'Texto del botón').click(); });
Como alternativa, puede utilizar page.evaluate()
para hacer clic en un elemento basado en su contenido de texto usando document.evaluate()
y una expresión XPath correspondiente:
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();
});
hizo una solución rápida para poder usar selectores css avanzados como “: contiene (texto)”
entonces usando esto biblioteca tu puedes sólo
const select = require ('puppeteer-select');
const element = await select(page).getElement('button:contains(Button text)');
await element.click()
La solucion es
(await page.$$eval(selector, a => a
.filter(a => a.textContent === 'target text')
))[0].click()
-
Considere reemplazar
filter(...)[0]
confind(...)
.– ggorlen
19 de marzo de 2022 a las 22:27
Kamen
Aquí está mi solución:
let selector="a";
await page.$$eval(selector, anchors => {
anchors.map(anchor => {
if(anchor.textContent == 'target text') {
anchor.click();
return
}
})
});
-
Considere reemplazar
filter(...)[0]
confind(...)
.– ggorlen
19 de marzo de 2022 a las 22:27
Ekeuwei
No hay una sintaxis de selector css compatible para el selector de texto o una opción de combinador, mi solución para esto sería:
await page.$$eval('selector', selectorMatched => {
for(i in selectorMatched)
if(selectorMatched[i].textContent === 'text string'){
selectorMatched[i].click();
break;//Remove this line (break statement) if you want to click on all matched elements otherwise the first element only is clicked
}
});
Compartió la respuesta aquí: stackoverflow.com/a/47829000/6161265
– Dr. Abu Taher
8 de enero de 2018 a las 0:30
¿Encontraste Respuesta?
– Shubham Batra
15 de enero de 2018 a las 5:55
Si ayuda, la página en la que quería hacer clic tiene jQuery cargado, así que pude y usé el método de evaluación para ejecutar el código jQuery.
– brandito
26 de febrero de 2018 a las 4:16