Selenium3 Python WebDriver API源码探析(3):定位Web元素

定位元素是任何与Web进行交互操作的基础,JavaScript如是,对于Selenium亦如是。只有定位到了元素,才能对元素进行操作。

Selenium中的两个基础元素定位方法(find_elementfind_elements

Selenium中使用find_elementfind_elements方法即可完成元素的定位。
我们先简单对比下这两个方法,再讲相关的细节:

  • find_element
    • 函数签名:def find_element(self, by=By.ID, value=None):
    • 函数参数:by为定位策略,value为定位策略对应的定位器
    • 调用对象:WebDriver实例或WebElement对象
    • 返回值:定位到元素时返回单个WebElement对象,没有定位到元素时抛出NoSuchElementException异常
  • find_elements
    • 函数签名:def find_elements(self, by=By.ID, value=None):
    • 函数参数:by为定位策略,value为定位策略对应的定位器
    • 调用对象:WebDriver实例或WebElement对象
    • 返回值:定位到元素时返回WebElement对象列表,没有定位到元素时返回空列表

返回值的差异

从上述函数的基本特性可知,这两个方法的参数,调用对象完全一样,差别主要在返回值上。返回值上的差异跟JavaScript中DOM的操作方法有些类似,element返回单个对象,elements返回对象列表,这是非常容易区别的差异。
find_element定位到元素的话,仅返回单个WebElement对象,没定位到元素就抛出异常。
find_elements定位到元素时返回WebElement对象列表,没有定位到元素时返回空列表。

调用对象

这两个方法的调用对象都可以为WebDriver实例或WebElement对象。

WebDriver实例我们可以认为就是Selenium启动的浏览器,这浏览器不单只是包含界面、控制等内容,最重要的是包含当前打开的页面。我们需要定位的元素(DOM 节点)就在这个页面中。因此,初始我们应该使用WebDriver实例调用这两个元素定位方法定位元素,得到返回的页面元素WebElement对象。由于页面元素是可以嵌套的,相应WebElement对象应该也可以定位元素。

根据selenium\webdriver\remote\webdriver.pyselenium\webdriver\remote\webelement.py源码可知,WebDriver对象和WebElement对象都具有find_elementfind_elements方法。Selenium中,这种设计方式被称为基于角色的接口。

Selenium中的定位策略

在前面讲到的两个方法中,都具有By参数,及定位策略 。Selenium中的定位策略定义在selenium\webdriver\common\by.py中。在使用定位策略时,可以导入Byfrom selenium.webdriver.common.by import By

class By(object):
    """
    Set of supported locator strategies.
    """

    ID = "id"
    XPATH = "xpath"
    LINK_TEXT = "link text"
    PARTIAL_LINK_TEXT = "partial link text"
    NAME = "name"
    TAG_NAME = "tag name"
    CLASS_NAME = "class name"
    CSS_SELECTOR = "css selector"
定位器 Locator 描述
class name 定位class属性与搜索值匹配的元素(不允许使用复合类名
css selector 定位 CSS 选择器匹配的元素
id 定位 id 属性与搜索值匹配的元素
name 定位 name 属性与搜索值匹配的元素
link text 定位link text可视文本与搜索值完全匹配的锚元素
partial link text 定位link text可视文本部分与搜索值部分匹配的锚点元素。如果匹配多个元素,则只选择第一个元素。
tag name 定位标签名称与搜索值匹配的元素
xpath 定位与 XPath 表达式匹配的元素

在上述策略中:
idclass namecss selector是比较推荐的策略,因为他们定位的范围较小。
xpath定位在某些情况下可读性、灵活性不强,需要学习xpath语法,但优势是大部分浏览器都支持复制元素的xpath,这样就不用自己编写xpath
tag name需要谨慎使用,因为按照标签名定位元素,往往返回大量元素。
link textpartial link text官方都不太建议使用,使用场景狭窄,底层其实是使用xpath实现的。

Selenium中的快捷定位接口

虽然find_elementfind_elements方法已经可以实现元素的定位功能,但是操作来比较繁琐。
因此Selenium根据8种不同的策略提供了16个快捷定位方法。

find_element_by_id(self, id_)
find_elements_by_id(self, id_)
find_element_by_name(self, name)
find_elements_by_name(self, name)
find_element_by_link_text(self, link_text)
find_elements_by_link_text(self, link_text)
find_element_by_partial_link_text(self, link_text)
find_elements_by_partial_link_text(self, link_text)
find_element_by_tag_name(self, name)
find_elements_by_tag_name(self, name)
find_element_by_xpath(self, xpath)
find_elements_by_xpath(self, xpath)
find_element_by_class_name(self, name)
find_elements_by_class_name(self, name)
find_element_by_css_selector(self, css_selector)
find_elements_by_css_selector(self, css_selector)

通过源码即可验证这些快捷方法与find_elementfind_elements之间的关系。

def find_element_by_id(self, id_):
    return self.find_element(by=By.ID, value=id_)

def find_elements_by_id(self, id_):
    return self.find_elements(by=By.ID, value=id_)

简易案例

from selenium import webdriver
from selenium.webdriver.common.by import By

driver = webdriver.Firefox()
driver.get("http://www.baidu.com")

btn1 = driver.find_element(By.ID, "su")
print(type(btn1))
btns1 = driver.find_elements(By.ID, "su")
print(type(btns1), len(btns1), type(btns1[0]))
btn2 = driver.find_element_by_id("su")
print(type(btn2))
btns2 = driver.find_elements_by_id("su")
print(type(btns2), len(btns2), type(btns2[0]))

猜你喜欢

转载自blog.csdn.net/mighty13/article/details/114635774
今日推荐