Selenium4引入了一些新特性,而Relative Locators就是其中之一。Relative Locators提供了以下5个方法:
above
below
to_left_of
to_right_of
near
我们来过一下这些方法。为了方便我们学习,我们先创建一个HTML文件,取名test.html:
- html>
- <html>
- <head>
- <meta charset="utf-8">
- <title>Just for testingtitle>
- head>
- <body>
- <h4>Nested Listh4>
- <ul>
- <li id="li1">li1li>
- <li id="li2">li2li>
- <li id="li3" class="cssstyle">
- <span id="span">test spanspan>
- li>
- <li id="li4" class="cssstyle">li4li>
- <li id="li5">li5li>
- ul>
-
- <span id="span1">span1span>
- <span id="span2">span2span>
- <span id="span3">span3span>
- <span id="span4" name="spanname4">span4span>
- <div class="cssstyle">
- Test div
- div>
-
- body>
- html>
并在python代码里生成测试用的webelement实例对象:
- driver.get("http://localhost:63342/selenium4_demo/test.html")
- li1 = driver.find_element(By.ID, "li1")
- li2 = driver.find_element(By.ID, "li2")
- li3 = driver.find_element(By.ID, "li3")
- li4 = driver.find_element(By.ID, "li4")
- li5 = driver.find_element(By.ID, "li5")
- span1 = driver.find_element(By.ID, "span1")
- span2 = driver.find_element(By.ID, "span2")
- span3 = driver.find_element(By.ID, "span3")
above(element_or_locator) --> 返回指定的页面元素或者定位字典上方元素的RelativeBy对象
below(element_or_locator) --> 返回指定的页面元素或者定位字典下方元素的RelativeBy对象
需要指出的是relative locators的所有方法都是支持链式访问的。
- for element in driver.find_elements(with_tag_name("li").below(li1).above(li5)):
- print(element.id, element.text, element.get_attribute("id"))
因为above和below返回的是RelativeBy对象,所以如果想要得到WebElement实例对象,还需要将RelativeBy对象作为传差传递给find_element()或者find_elements()方法。
代码的输出如下:
bf539a5c-afa6-4c31-a182-1a60453a5ee3 test span li3
这里有些奇怪的是,理应返回li2, li3和li4才对,但在我给定的测试HTML里,确实只返回了li3。经过多次实验,above和below都忽略了离它们最近的一个符合条件的页面元素,比如below(li1)只返回li3,li4和li5, 而above(li5)只返回了li3,li2和li1。这直接导致我们的链式访问只返回li3一个元素。
2. to_left_of和to_right_of
to_left_of(element_or_locator) --> 返回指定的页面元素或者定位字典左方元素的RelativeBy对象
to_right_of(element_or_locator) --> 返回指定的页面元素或者定位字典右方元素的RelativeBy对象
- print(driver.find_element(with_tag_name("span").to_left_of(span2)).text)
- print(driver.find_element(locate_with(By.NAME, "spanname4").to_right_of(span2)).text)
我们不光可以用tag_name来筛选相对位置的页面元素,也支持NAME,ID,CLASS_NAME等筛选方式。
输出:
- span1
- span4
3. near
near(element_or_locator) --> 返回指定页面元素50PX内的页面元素的RelativeBy对象
- for element in driver.find_elements(with_tag_name("li").near({By.ID: "li3"})):
- print(element.id, element.text, element.get_attribute("id"))
- print(driver.find_element(with_tag_name("span").near(li2)).text)
输出:
- f1104e9c-d1a8-4b10-9019-bb579ca4c427 li2 li2
- e416a7b4-0ad1-4d67-9cf4-bfaa13edb58f li4 li4
- c80b0456-9641-41c8-b3be-13421f020815 li1 li1
- 746f1190-8fa0-4779-8442-2b86f0e3444f li5 li5
- span3
在Selenium4发布之前,Locator包括class name, css selector, id, name, link text, partial link text, tag name和xpath。坦白说,我的理解是,relative locators的出现,并不是解决能或是不能的问题,而是解决难或是易的问题。relative locators每个单独的方法都显得不是特别实用和必要,但是通过链式的组合定位,确实让一些原来难以定位的元素变得更加容易定位,并且可以做到更加优雅。也为我们在定位元素时提供了更多的选择。👍👍👍