我正在尝试使用以下XPath表达式刮取项目型号旁边的文本64076:在this page上:
//*[contains (@id,'productDetails')]//tr[contains(.,'Item model number')]/td|//*[contains (@id,'detail')]//descendant::li[contains(.,'Item model number')]/text() // I'm focusing mainly on second half of expression..
但是,尽管这与Firebug中的预期文本(64076)匹配,但在使用Selenium WebDriver(Java)时未找到它。
当我将XPath更改为:
//*[contains (@id,'productDetails')]//tr[contains(.,'Item model number')]/td|//*[contains (@id,'detail')]//descendant::li[contains(.,'Item model number')]
它工作但它也刮擦文本项目模型编号:我不想要(我知道我可以使用正则表达式解析结果,但我试图理解为什么我的XPath不工作,因为我明显匹配实际的文本/数字通过text()
,而不是粗体文字)
谢谢
这是因为XPath中的text()
意味着找到TextNode,但是Selenium只支持查找和返回ElementNode。 Selenium也不支持属性节点,但XPath支持。
你必须找到TextNode的父(它是一个ElementNode),然后使用正则表达式或拆分来提取你想要的刺痛。
String xpath = "//ul/li[b[text()='Item model number:']][contains(. , '64076')]"
driver.findElement(By.xpath(xpath)).getText().split()[1]
这是selenium中的常见问题,因为它只支持不包含text()
的XPath 1.0。通常的方法是获取节点并调用getText()
。
Here是一个很好的包装函数来获取没有来自孩子的任何文本的文本:
public static String geNodeText(WebElement element) {
String text = element.getText();
for (WebElement child : element.findElements(By.xpath("./*"))) {
text = text.replaceFirst(child.getText(), "");
}
return text;
}
果然,你可以使用字符串函数或正则表达式来提取有问题的字符串。但这可能需要您为每种情况编写自定义提取逻辑。
您不能使用Selenium直接获取它,因为它是TextNode。您可以使用JavaScript来检查文本节点并获取它。
WebElement itemModelRootNode = driver.findElement(by.xpath("//*[contains (@id,'productDetails')]//tr[contains(.,'Item model number')]/td|//*[contains (@id,'detail')]//descendant::li[contains(.,'Item model number')]");
String script = "var t = ''; arguments[0].childNodes.forEach((node)=>{ if(node.nodeType==Node.TEXT_NODE && node.textContent.trim().length > 0) { t = node.textContent.trim(); } }); return t;"
String text = ((JavascriptExecutor)driver).executeScript(script, itemModelRootNode);
更多@Bauban答案。 Selenium不允许使用文本节点定位元素。您可以尝试使用evaluate()
JavaScript方法并使用JavascriptExecutor
评估您的xpath
这是你的xpath:
//div[@class='content']//li[contains(.,'Item model number:')]/text()
这就是你如何评价:
JavascriptExecutor js = (JavascriptExecutor)driver;
Object message = js.executeScript("var value = document.evaluate(\"//div[@class='content']//li[contains(.,'Item model number:')]/text()\",document, null, XPathResult.STRING_TYPE, null ); return value.stringValue;");
System.out.println(message.toString().trim());
您可以参考this链接以获取有关评估功能的更多详细信息。
根据你分享的url提取文本64076旁边的文本:在this page上,因为它是一个文本节点,你需要使用WebDriverWait来显示所需的元素,你可以使用以下解决方案:
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
public class q52359631_textExtract {
public static void main(String[] args) {
System.setProperty("webdriver.gecko.driver", "C:\\Utility\\BrowserDrivers\\geckodriver.exe");
WebDriver driver = new FirefoxDriver();
driver.get("https://www.amazon.com/dp/B000TW3B9G/?tag=stackoverflow17-20");
WebElement myElement = new WebDriverWait(driver, 20).until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//td[@class='bucket']//li/b[contains(.,'Item model number:')]/..")));
String myText = (String)((JavascriptExecutor)driver).executeScript("return arguments[0].lastChild.textContent;", myElement);
System.out.println(myText);
}
}
64076
尝试Item model number: 64076
测试URL
var xpathExp =
"//h2[.='Product details']//parent::td//div[@class='content']/ul/li/b[contains(text(),'Item')]/parent::li/text()";
var ele = $x(xpathExp);
console.dir( ele ); // Array(1)
console.log( ele[0] ); //" 64076"
测试XML XPath online
:
<ul>
<li>
<b>Item model number:</b> 64076
</li>
</ul>
XML树视图codebeautify //ul/li/b[contains(text(),'Item')]/parent::li/text()
ul ..
li 64076 ..
b Item model number:
html作为javascript对象
outerHTML:"<li><b>Item model number:</b> 64076</li>"
outerText:"Item model number: 64076"
tagName:"LI"
textContent:"Item model number: 64076"
lastChild:text
data: 64076"
nodeValue: 64076"
textContent: 64076"
wholeText: 64076"
lastElementChild:b