Wie kann ich den Text eines Elements in Selenium WebDriver abrufen, ohne den Text des untergeordneten Elements einzuschließen?
Lesezeit: 5 Minuten
Josch
In Betracht ziehen:
<div id="a">This is some
<div id="b">text</div>
</div>
“This is some” zu bekommen ist nicht trivial. Zum Beispiel gibt dies “This is some text” zurück:
driver.find_element_by_id('a').text
Wie erhält man im Allgemeinen den Text eines bestimmten Elements, ohne den Text seiner Kinder einzubeziehen?
Also fürs Protokoll, ich habe es letztendlich in Javascript gemacht … Ich habe jQuery auf den Seiten, die ich teste, also habe ich die Tatsache ausgenutzt, dass Selenium automatisch Dom-Elemente konvertiert, die von Javascript in WebElements zurückgegeben werden: my_result = driver .execute_script(‘zurück […call to my jquery function..]’)
Das an die Funktion übergebene Element kann aus der abgerufen werden find_element...() Methoden (d.h. es kann a WebElement Objekt).
Oder wenn Sie jQuery nicht haben oder es nicht verwenden möchten, können Sie den Hauptteil der Funktion oben durch diesen ersetzen:
return self.driver.execute_script("""
var parent = arguments[0];
var child = parent.firstChild;
var ret = "";
while(child) {
if (child.nodeType === Node.TEXT_NODE)
ret += child.textContent;
child = child.nextSibling;
}
return ret;
""", element)
Ich verwende diesen Code tatsächlich in einer Testsuite.
Richtig, was mir im Grunde klar wurde, ist … verwenden Sie nicht die Suchmethoden von Selenium, verwenden Sie einfach jquery
– Josch
26. September 2013 um 23:59 Uhr
@josh, dem würde ich nicht zustimmen … Seleniums-Methoden sollen Interaktionen aus dem POV eines Benutzers nachahmen, während jQuery dies nicht ist. Ja, Sie können beide verwenden, um Elemente zu erfassen, aber im Allgemeinen sollte es relativ wenige Situationen geben, in denen Sie Javascript ausführen müssen.
– Wlingke
16. Dezember 2013 um 15:46 Uhr
Das erste Code-Snippet geht davon aus, dass jQuery auf der Seite geladen wird. Das zweite Code-Snippet funktioniert unabhängig davon, ob jQuery geladen ist oder nicht.
– Ludwig
21. April 2016 um 12:40 Uhr
unentdecktes Selen
In dem von Ihnen geteilten HTML:
<div id="a">This is some
<div id="b">text</div>
</div>
Der Text This is some ist innerhalb von a Textknoten. Zur Darstellung der Textknoten strukturiert:
<div id="a">
This is some
<div id="b">text</div>
</div>
Dieser Anwendungsfall
Zum Extrahieren und Drucken des Textes This is some von dem Textknoten Mit dem Python-Client von Selenium haben Sie zwei Möglichkeiten:
Verwenden splitlines(): Sie können das übergeordnete Element identifizieren, dh <div id="a">extrahieren Sie die innerHTML und dann verwenden splitlines() folgendermaßen:
Verwenden execute_script(): Sie können auch die verwenden execute_script() Methode, die JavaScript im aktuellen Fenster/Frame wie folgt synchron ausführen kann:
Auf das zweite „using xpath“ folgt „find_element_by_css_selector“.
– Peter Mortensen
15. November um 2:48 Uhr
Josch
Verwenden:
def get_true_text(tag):
children = tag.find_elements_by_xpath('*')
original_text = tag.text
for child in children:
original_text = original_text.replace(child.text, '', 1)
return original_text
das läuft aber ekelhaft langsam… das muss doch besser gehen??
– Josch
7. September 2012 um 21:39 Uhr
Sie sollten immer versuchen, ein möglichst spezifisches untergeordnetes Element zu erhalten. In diesem Fall wird es langsam laufen, wenn Sie viele untergeordnete Elemente haben. Warum prüfen Sie nicht, ob das Element tatsächlich Text enthält, bevor Sie zurückkehren, dh machen Sie den XPath: *[string-length(text()) > 1] oder machen Sie die for-Schleife auf prüfen child.text nicht null und nicht leer sein. Und was ist mit dem CSS-Selektor? XPath-Abfragen sind sowieso sehr langsam, daher ist ein CSS-Selektor möglicherweise schneller.
– Arran
7. September 2012 um 23:53 Uhr
kreativitea
Du musst keinen Ersatz machen. Sie können die Länge des untergeordneten Textes ermitteln, diese von der Gesamtlänge subtrahieren und in den ursprünglichen Text schneiden. Das sollte wesentlich schneller gehen.
Pikamander2
Leider wurde Selenium nur dafür gebaut, damit zu arbeiten Elementenicht Text Knoten.
Wenn Sie versuchen, eine Funktion wie z get_element_by_xpath Um auf die Textknoten abzuzielen, wirft Selenium eine InvalidSelectorException.
Eine Problemumgehung besteht darin, den relevanten HTML-Code mit Selenium abzurufen und dann eine HTML-Parsing-Bibliothek wie z Schöne Suppe die Textknoten eleganter behandeln kann.
Von dort aus gibt es mehrere Möglichkeiten, nach dem Textinhalt zu suchen. Sie müssen experimentieren, um zu sehen, was für Ihren Anwendungsfall am besten funktioniert.
Hier ist ein einfacher Einzeiler, der ausreichen könnte:
inner_soup.find(text=True)
Wenn das nicht funktioniert, können Sie die untergeordneten Knoten des Elements mit .contents() durchlaufen und ihren Objekttyp überprüfen.
Schöne Suppe hat vier Arten von Elementenund derjenige, an dem Sie interessiert sein werden, ist der NavigierbarerString -Typ, der von Textknoten erzeugt wird. Im Gegensatz dazu haben Elemente einen Typ von Schild.
contents = inner_soup.contents
for bs4_object in contents:
if (type(bs4_object) == bs4.Tag):
print("This object is an Element.")
elif (type(bs4_object) == bs4.NavigableString):
print("This object is a Text node.")
Beachten Sie, dass Beautiful Soup keine XPath-Ausdrücke unterstützt. Wenn Sie diese benötigen, können Sie einige der Problemumgehungen in dieser Frage verwenden.
14367400cookie-checkWie kann ich den Text eines Elements in Selenium WebDriver abrufen, ohne den Text des untergeordneten Elements einzuschließen?yes
Also fürs Protokoll, ich habe es letztendlich in Javascript gemacht … Ich habe jQuery auf den Seiten, die ich teste, also habe ich die Tatsache ausgenutzt, dass Selenium automatisch Dom-Elemente konvertiert, die von Javascript in WebElements zurückgegeben werden: my_result = driver .execute_script(‘zurück […call to my jquery function..]’)
– Josch
10. September 2012 um 19:03 Uhr