查找 Web 元素
使用 Selenium 最基本的方面之一是获取要操作的元素引用。Selenium 提供了许多内置的定位器策略来唯一标识元素。在非常高级的场景中,有多种使用定位器的方法。为了本文档的目的,让我们考虑一下这个 HTML 代码片段
<ol id="vegetables">
<li class="potatoes">…
<li class="onions">…
<li class="tomatoes"><span>Tomato is a Vegetable</span>…
</ol>
<ul id="fruits">
<li class="bananas">…
<li class="apples">…
<li class="tomatoes"><span>Tomato is a Fruit</span>…
</ul>
第一个匹配的元素
许多定位器将匹配页面上的多个元素。单个查找元素方法将返回给定上下文中找到的第一个元素的引用。
评估整个 DOM
当在驱动程序实例上调用查找元素方法时,它会返回 DOM 中与提供的定位器匹配的第一个元素的引用。此值可以存储并用于将来的元素操作。在上面的 HTML 示例中,有两个元素的类名为“tomatoes”,因此此方法将返回“vegetables”列表中的元素。
WebElement vegetable = driver.findElement(By.className("tomatoes"));
vegetable = driver.find_element(By.CLASS_NAME, "tomatoes")
var vegetable = driver.FindElement(By.ClassName("tomatoes"));
fruits = driver.find_element(id: 'fruits')
fruit = fruits.find_element(class: 'tomatoes')
const vegetable = await driver.findElement(By.className('tomatoes'));
val vegetable: WebElement = driver.findElement(By.className("tomatoes"))
评估 DOM 的子集
与其在整个 DOM 中查找唯一的定位器,不如将搜索范围缩小到另一个已定位的元素的范围内通常会很有用。在上面的示例中,有两个类名为“tomatoes”的元素,要获取第二个元素的引用有点困难。
一种解决方案是定位具有唯一属性的元素,该属性是所需元素的祖先,而不是不想要的元素的祖先,然后在该对象上调用查找元素
WebElement fruits = driver.findElement(By.id("fruits"));
WebElement fruit = fruits.findElement(By.className("tomatoes"));
fruits = driver.find_element(By.ID, "fruits")
fruit = fruits.find_element(By.CLASS_NAME,"tomatoes")
IWebElement fruits = driver.FindElement(By.Id("fruits"));
IWebElement fruit = fruits.FindElement(By.ClassName("tomatoes"));
fruits = driver.find_element(id: 'fruits')
fruit = fruits.find_element(class: 'tomatoes')
const fruits = await driver.findElement(By.id('fruits'));
const fruit = fruits.findElement(By.className('tomatoes'));
val fruits = driver.findElement(By.id("fruits"))
val fruit = fruits.findElement(By.className("tomatoes"))
Java 和 C#WebDriver
、WebElement
和 ShadowRoot
类都实现了一个 SearchContext
接口,该接口被认为是基于角色的接口。基于角色的接口允许你确定特定的驱动程序实现是否支持给定的功能。这些接口定义明确,并尽量坚持只有一个责任角色。
评估 Shadow DOM
Shadow DOM 是隐藏在元素内的封装 DOM 树。随着 Chromium 浏览器 v96 的发布,Selenium 现在允许你使用易于使用的 shadow root 方法访问此树。注意:这些方法需要 Selenium 4.0 或更高版本。
WebElement shadowHost = driver.findElement(By.cssSelector("#shadow_host"));
SearchContext shadowRoot = shadowHost.getShadowRoot();
WebElement shadowContent = shadowRoot.findElement(By.cssSelector("#shadow_content"));
shadow_host = driver.find_element(By.CSS_SELECTOR, '#shadow_host')
shadow_root = shadow_host.shadow_root
shadow_content = shadow_root.find_element(By.CSS_SELECTOR, '#shadow_content')
var shadowHost = _driver.FindElement(By.CssSelector("#shadow_host"));
var shadowRoot = shadowHost.GetShadowRoot();
var shadowContent = shadowRoot.FindElement(By.CssSelector("#shadow_content"));
shadow_host = @driver.find_element(css: '#shadow_host')
shadow_root = shadow_host.shadow_root
shadow_content = shadow_root.find_element(css: '#shadow_content')
优化的定位器
嵌套查找可能不是最有效的定位策略,因为它需要向浏览器发出两个单独的命令。
为了稍微提高性能,我们可以使用 CSS 或 XPath 在单个命令中找到此元素。请参阅我们的定位器策略建议,位于推荐的测试实践部分。
对于此示例,我们将使用 CSS 选择器
WebElement fruit = driver.findElement(By.cssSelector("#fruits .tomatoes"));
fruit = driver.find_element(By.CSS_SELECTOR,"#fruits .tomatoes")
var fruit = driver.FindElement(By.CssSelector("#fruits .tomatoes"));
fruit = driver.find_element(css: '#fruits .tomatoes')
const fruit = await driver.findElement(By.css('#fruits .tomatoes'));
val fruit = driver.findElement(By.cssSelector("#fruits .tomatoes"))
所有匹配的元素
有几种用例需要获取与定位器匹配的所有元素的引用,而不是仅仅获取第一个元素的引用。复数查找元素方法返回元素引用集合。如果没有匹配项,则返回空列表。在这种情况下,所有水果和蔬菜列表项的引用将返回在一个集合中。
List<WebElement> plants = driver.findElements(By.tagName("li"));
plants = driver.find_elements(By.TAG_NAME, "li")
IReadOnlyList<IWebElement> plants = driver.FindElements(By.TagName("li"));
plants = driver.find_elements(tag_name: 'li')
const plants = await driver.findElements(By.tagName('li'));
val plants: List<WebElement> = driver.findElements(By.tagName("li"))
获取元素
通常,你会获得一个元素集合,但希望使用特定的元素,这意味着你需要迭代集合并识别你想要的元素。
List<WebElement> elements = driver.findElements(By.tagName("li"));
for (WebElement element : elements) {
System.out.println("Paragraph text:" + element.getText());
}
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Firefox()
# Navigate to Url
driver.get("https://www.example.com")
# Get all the elements available with tag name 'p'
elements = driver.find_elements(By.TAG_NAME, 'p')
for e in elements:
print(e.text)
using OpenQA.Selenium;
using OpenQA.Selenium.Firefox;
using System.Collections.Generic;
namespace FindElementsExample {
class FindElementsExample {
public static void Main(string[] args) {
IWebDriver driver = new FirefoxDriver();
try {
// Navigate to Url
driver.Navigate().GoToUrl("https://example.com");
// Get all the elements available with tag name 'p'
IList < IWebElement > elements = driver.FindElements(By.TagName("p"));
foreach(IWebElement e in elements) {
System.Console.WriteLine(e.Text);
}
} finally {
driver.Quit();
}
}
}
}
elements = driver.find_elements(:tag_name,'p')
elements.each { |e| puts e.text }
const {Builder, By} = require('selenium-webdriver');
(async function example() {
let driver = await new Builder().forBrowser('firefox').build();
try {
// Navigate to Url
await driver.get('https://www.example.com');
// Get all the elements available with tag 'p'
let elements = await driver.findElements(By.css('p'));
for(let e of elements) {
console.log(await e.getText());
}
}
finally {
await driver.quit();
}
})();
import org.openqa.selenium.By
import org.openqa.selenium.firefox.FirefoxDriver
fun main() {
val driver = FirefoxDriver()
try {
driver.get("https://example.com")
// Get all the elements available with tag name 'p'
val elements = driver.findElements(By.tagName("p"))
for (element in elements) {
println("Paragraph text:" + element.text)
}
} finally {
driver.quit()
}
}
从元素查找元素
它用于查找父元素上下文中匹配的子 WebElement 的列表。要实现这一点,父 WebElement 与“findElements”链接以访问子元素
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import java.util.List;
public class findElementsFromElement {
public static void main(String[] args) {
WebDriver driver = new ChromeDriver();
try {
driver.get("https://example.com");
// Get element with tag name 'div'
WebElement element = driver.findElement(By.tagName("div"));
// Get all the elements available with tag name 'p'
List<WebElement> elements = element.findElements(By.tagName("p"));
for (WebElement e : elements) {
System.out.println(e.getText());
}
} finally {
driver.quit();
}
}
}
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.get("https://www.example.com")
##get elements from parent element using TAG_NAME
# Get element with tag name 'div'
element = driver.find_element(By.TAG_NAME, 'div')
# Get all the elements available with tag name 'p'
elements = element.find_elements(By.TAG_NAME, 'p')
for e in elements:
print(e.text)
##get elements from parent element using XPATH
##NOTE: in order to utilize XPATH from current element, you must add "." to beginning of path
# Get first element of tag 'ul'
element = driver.find_element(By.XPATH, '//ul')
# get children of tag 'ul' with tag 'li'
elements = driver.find_elements(By.XPATH, './/li')
for e in elements:
print(e.text)
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using System.Collections.Generic;
namespace FindElementsFromElement {
class FindElementsFromElement {
public static void Main(string[] args) {
IWebDriver driver = new ChromeDriver();
try {
driver.Navigate().GoToUrl("https://example.com");
// Get element with tag name 'div'
IWebElement element = driver.FindElement(By.TagName("div"));
// Get all the elements available with tag name 'p'
IList < IWebElement > elements = element.FindElements(By.TagName("p"));
foreach(IWebElement e in elements) {
System.Console.WriteLine(e.Text);
}
} finally {
driver.Quit();
}
}
}
}
element = driver.find_element(:tag_name,'div')
elements = element.find_elements(:tag_name,'p')
elements.each { |e| puts e.text }
const {Builder, By} = require('selenium-webdriver');
(async function example() {
let driver = new Builder()
.forBrowser('chrome')
.build();
await driver.get('https://www.example.com');
// Get element with tag name 'div'
let element = driver.findElement(By.css("div"));
// Get all the elements available with tag name 'p'
let elements = await element.findElements(By.css("p"));
for(let e of elements) {
console.log(await e.getText());
}
})();
import org.openqa.selenium.By
import org.openqa.selenium.chrome.ChromeDriver
fun main() {
val driver = ChromeDriver()
try {
driver.get("https://example.com")
// Get element with tag name 'div'
val element = driver.findElement(By.tagName("div"))
// Get all the elements available with tag name 'p'
val elements = element.findElements(By.tagName("p"))
for (e in elements) {
println(e.text)
}
} finally {
driver.quit()
}
}
获取活动元素
它用于跟踪(或)查找当前浏览上下文中具有焦点的 DOM 元素。
import org.openqa.selenium.*;
import org.openqa.selenium.chrome.ChromeDriver;
public class activeElementTest {
public static void main(String[] args) {
WebDriver driver = new ChromeDriver();
try {
driver.get("http://www.google.com");
driver.findElement(By.cssSelector("[name='q']")).sendKeys("webElement");
// Get attribute of current active element
String attr = driver.switchTo().activeElement().getAttribute("title");
System.out.println(attr);
} finally {
driver.quit();
}
}
}
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.get("https://www.google.com")
driver.find_element(By.CSS_SELECTOR, '[name="q"]').send_keys("webElement")
# Get attribute of current active element
attr = driver.switch_to.active_element.get_attribute("title")
print(attr)
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
namespace ActiveElement {
class ActiveElement {
public static void Main(string[] args) {
IWebDriver driver = new ChromeDriver();
try {
// Navigate to Url
driver.Navigate().GoToUrl("https://www.google.com");
driver.FindElement(By.CssSelector("[name='q']")).SendKeys("webElement");
// Get attribute of current active element
string attr = driver.SwitchTo().ActiveElement().GetAttribute("title");
System.Console.WriteLine(attr);
} finally {
driver.Quit();
}
}
}
}
driver.find_element(css: '[name="q"]').send_keys('webElement')
attr = driver.switch_to.active_element.attribute('title')
const {Builder, By} = require('selenium-webdriver');
(async function example() {
let driver = await new Builder().forBrowser('chrome').build();
await driver.get('https://www.google.com');
await driver.findElement(By.css('[name="q"]')).sendKeys("webElement");
// Get attribute of current active element
let attr = await driver.switchTo().activeElement().getAttribute("title");
console.log(`${attr}`)
})();
import org.openqa.selenium.By
import org.openqa.selenium.chrome.ChromeDriver
fun main() {
val driver = ChromeDriver()
try {
driver.get("https://www.google.com")
driver.findElement(By.cssSelector("[name='q']")).sendKeys("webElement")
// Get attribute of current active element
val attr = driver.switchTo().activeElement().getAttribute("title")
print(attr)
} finally {
driver.quit()
}
}