Gibt es eine Methode (in der API nicht gefunden) oder eine Lösung, um auf ein Element mit Text zu klicken?
Zum Beispiel habe ich HTML:
<div class="elements">
<button>Button text</button>
<a href=#>Href text</a>
<div>Div text</div>
</div>
Und ich möchte auf ein Element klicken, in das Text eingeschlossen ist (klicken Sie auf die Schaltfläche in .elements), wie:
Page.click('Button text', '.elements')
Antworten:
Die aktuelle Top-Antwort von tokland funktioniert nur auf Textknoten und nicht auf Knoten mit anderen Elementen.
Kurze Antwort
Dieser XPath-Ausdruck fragt eine Schaltfläche ab, die den Text "Schaltflächentext" enthält:
const [button] = await page.$x("//button[contains(., 'Button text')]"); if (button) { await button.click(); }
<div class="elements">
Verwenden Sie den folgenden Code, um auch die Umgebung der Schaltflächen zu berücksichtigen:const [button] = await page.$x("//div[@class='elements']/button[contains(., 'Button text')]");
Erläuterung
text()
Schauen wir uns ein Beispiel an, um zu erklären, warum die Verwendung des Textknotens ( ) in einigen Fällen falsch ist:<div> <button>Start End</button> <button>Start <em>Middle</em> End</button> </div>
Lassen Sie uns zunächst die Ergebnisse überprüfen, wenn Sie Folgendes verwenden
contains(text(), 'Text')
://button[contains(text(), 'Start')]
gibt beide zwei Knoten zurück (wie erwartet)//button[contains(text(), 'End')]
gibt nur einen Knoten (den ersten) zurück, datext()
eine Liste mit zwei Texten (Start
undEnd
) zurückgegebencontains
wird, überprüft aber nur den ersten//button[contains(text(), 'Middle')]
gibt keine Ergebnisse zurück, datext()
der Text der untergeordneten Knoten nicht enthalten istHier sind die XPath-Ausdrücke für
contains(., 'Text')
, die für das Element selbst einschließlich seiner untergeordneten Knoten funktionieren://button[contains(., 'Start')]
kehren beide zwei Tasten//button[contains(., 'End')]
wird wieder die beiden Rück zwei Tasten//button[contains(., 'Middle')]
gibt eins zurück (die letzte Taste)In den meisten Fällen ist es daher sinnvoller, den Ausdruck
.
anstelle vontext()
in einem XPath-Ausdruck zu verwenden.quelle
//*[...]
stattdessen verwenden.Sie können einen XPath-Selektor mit Seite verwenden. $ X (Ausdruck) :
Ein vollständiges Beispiel finden Sie
clickByText
in dieser Übersicht . Es kümmert sich um das Entkommen von Anführungszeichen, was bei XPath-Ausdrücken etwas schwierig ist.quelle
//a[contains
durch//*[contains
, um ein beliebiges Element auszuwählen, nicht nur ein anchor (a
) -Element.Sie können auch
page.evaluate()
auf Elemente klickendocument.querySelectorAll()
, die nach Textinhalten gefiltert wurden:await page.evaluate(() => { [...document.querySelectorAll('.elements button')].find(element => element.textContent === 'Button text').click(); });
Alternativ können
page.evaluate()
Sie ein Element basierend auf seinem Textinhalt mitdocument.evaluate()
und einem entsprechenden XPath-Ausdruck anklicken :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(); });
quelle
schnelle Lösung gemacht, um erweiterte CSS-Selektoren wie ": enthält (Text)" verwenden zu können
Mit dieser Bibliothek können Sie also einfach
quelle
Hier ist meine Lösung:
quelle
Die Lösung ist
quelle
Es gibt keine unterstützte CSS-Auswahlsyntax für die Textauswahl oder eine Kombinatoroption. Meine Lösung hierfür wäre:
quelle
Es gibt viele Antworten, die darauf hindeuten,
contains
aber ich sehe keine Motivation für diese Ungenauigkeit angesichts des Anwendungsfalls von OP, der anscheinend genau mit einer Zielzeichenfolge von"Button text"
und einem Element übereinstimmt<button>Button text</button>
.Ich würde es vorziehen, die präzisere zu verwenden
[text()="Button text"]
, die ein falsches Positiv vermeidet, wenn die Schaltfläche beispielsweise lautet<button>Button text and more stuff</button>
:Dies nimmt das entgegengesetzte Szenario dieser Antwort vorweg , das versucht, so freizügig wie möglich zu sein.
Viele Antworten haben auch die
.elements
Anforderungen der Elternklasse verfehlt .quelle
Ich musste:
await this.page.$eval(this.menuSelector, elem => elem.click());
quelle