掌握 Selenium 中的 XPath:如何定位元素

测试工程师在软件开发周期中扮演着不可或缺的角色,他们负责确保团队交付的应用程序没有任何错误,并且运行高效。这些工程师会在应用程序发布或向用户开放之前,对其进行多方面的测试。

测试人员需要具备熟练的技能,能够定位并与网页元素进行互动。Selenium是当今开发团队中最常用的自动化测试工具之一。该工具包含四个主要组成部分:Selenium Grid、Selenium WebDriver、Selenium IDE和Selenium RC。

我们今天的重点将放在Selenium WebDriver上,因为它集成了XPath。本文将详细阐述XPath的概念,探讨其基本语法,并展示如何在Selenium中使用XPath。

什么是XPath

XPath,即XML路径语言,是一种强大的查询语言,用于在XML文档中选择和导航属性和元素。XPath通过定义路径表达式,提供了一种精准定位XML文档特定部分并提取信息的方法。

它的语法类似于文件系统的路径结构。此外,它还具有各种功能和符号,可以根据属性和层次结构轻松选择元素。您可以将XPath与XML、HTML和XSLT等技术结合使用,实现数据的提取和操作。

为什么要使用XPath?

  • 灵活性强:与只能使用标签名、ID或类名定位元素的CSS选择器不同,XPath允许您使用其他属性来定位元素。
  • 可重用性:您可以将XPath表达式存储在变量中,并在代码中多次使用。
  • 精确的节点选择:XPath提供了一种标准化的方法,用于定位Web文档中的特定元素。

XPath的基本语法

XPath允许您通过DOM查找网页上的任何元素。在深入研究语法之前,我们需要理解以下XPath表达式的含义:

表达式说明:

`节点名称/标记名称` 选择所有名称为“节点名称”或“标记名称”的节点。
`/` 从根节点开始选择。
`//` 从当前文档中与选择匹配的任意节点开始选择。
`.` 选择当前节点。
`@` 选择属性。

XPath的标准语法结构如下:

XPath=//标签名[@属性="值"]

如你所见,语法以双斜杠(//)开头,它从以标签/节点名称定义的当前节点开始。

绝对XPath与相对XPath

在处理XPath时,我们有两种主要的方式:绝对XPath和相对XPath。

绝对XPath

绝对XPath是从根节点到目标元素的直接路径。它从根节点开始,最终到达目标节点。

以下是一个HTML文档的示例:

<!DOCTYPE html>
<html>
<head>
    <title>techblik.com</title>
</head>
<body>
    <div>
        <h1>Welcome to techblik.com</h1>
    </div>
</body>
</html>

如果我们想要定位内容为“Welcome to techblik.com”的元素,其绝对路径如下:

/html/body/div/h1

在上述文档中,我们有:

  • `html` 作为根节点: `/html`
  • `body` 作为父节点: `/html/body`
  • `div` 作为 `body` 节点的子节点: `/html/body/div`
  • `h1` 作为 `div` 节点的子节点: `/html/body/div/h1`

为了获取最内部的元素,您必须遵循完整的路径。

何时使用绝对XPath

绝对XPath遵循特定的路径。当页面上有多个具有相似属性的元素时,绝对XPath非常有用,它可以确保您定位到文档上的确切元素。

然而,绝对XPath对HTML文档结构的细微变化非常敏感。因此,即使是一个小的更改也可能破坏你的绝对XPath表达式。

相对XPath

相对XPath从任意节点开始,最终到达目标节点。这种路径不容易受到文档结构变化的影响,因此在大多数情况下更受欢迎。使用相对XPath,您可以从文档的任何部分开始定位元素。相对XPath表达式以双斜杠“//”开头。

如果我们仍然使用相同的HTML文档,我们可以找到标题为“Welcome to techblik.com”的`h1`元素:

<!DOCTYPE html>
<html>
<head>
    <title>techblik.com</title>
</head>
<body>
    <div>
        <h1>Welcome to techblik.com</h1>
    </div>
</body>
</html>

此`h1`元素的相对XPath为:

//body/div/h1

何时使用相对XPath

当您需要在灵活性和精确性之间取得平衡时,应该使用相对XPath。只要元素之间的关系保持不变,此路径就能够适应HTML文档中的变化。

在Selenium中使用XPath定位元素

Selenium是一个开源框架,允许用户自动化Web浏览器。该框架提供了一系列库和工具,帮助测试人员以自动化的方式与Web元素进行交互。

假设我们有一个包含歌曲列表的Web文档,如下所示:

<!DOCTYPE html>
<html>
<head>
    <title>Song Library</title>
</head>
<body>
    <h1>Song Library</h1>
    <ul class="song-list">
        <li class="song" title="Song Title 1">Song 1 - Artist 1</li>
        <li class="song" title="Song Title 2">Song 2 - Artist 2</li>
        <li class="song" title="Song Title 3">Song 3 - Artist 1</li>
        <li class="song" title="Song Title 4">Song 4 - Artist 3</li>
    </ul>
</body>
</html>
  • 我们的根节点是“。
  • “ 是其父节点。
  • `

    ` 是`` 的子节点。

  • `
      ` 也是`` 的子节点。
  • `
  • ` 是`
      ` 的子元素。

我们可以在上面的HTML文档中使用不同的XPath定位器。例如,我们可以通过ID、名称、类名、包含、文本、结尾、开头以及其他多种定位器来定位元素。您可以将Selenium与各种编程语言结合使用。这里,我们将使用Python进行演示。

按索引查找

假设我们想要找到第三首歌曲,我们可以使用以下代码:

third_song = driver.find_element_by_xpath("//li[@class="song"][3]")
print("Third Song:", third_song.text)

我们使用了相对XPath并从“li”节点开始。当Selenium找到列表中的第三首歌曲时,它将打印其文本内容。

按属性定位

我们可以使用XPath查找“Artist 1”的所有歌曲并打印其标题。相应的代码如下:

songs_by_artist1 = driver.find_elements_by_xpath("//li[contains(@class, 'song') and contains(text(), 'Artist 1')]")
print("Songs by Artist 1:")
for song in songs_by_artist1:
    print(song.text)

通过文本定位

这种定位器可帮助您查找具有特定文本的元素。例如,我们可以查找标题中包含“Song 4”的歌曲并打印其文本。我们可以使用这段代码来实现这个定位:

song_with_text = driver.find_element_by_xpath("//li[contains(text(), 'Song 4')]")
print("Song with Text:", song_with_text.text)

XPath轴

到目前为止我们讨论的方法可以完美地处理简单的网页。但是,在某些情况下,XPath元素搜索方法(如文本、ID、类名和名称)可能无法正常工作。

XPath轴在常规定位器无法有效工作时用于定位动态内容。通过XPath轴,您可以根据元素与其他元素的关系来定位元素。以下是一些常用的XPath轴定位器:

祖先

祖先轴方法非常适合处理具有深度嵌套元素的XML文档。它可以选择当前节点的所有祖先元素,从最近的祖父母和父母到更远的祖先。

以下代码片段展示了如何使用祖先轴:

<bookstore>
  <book>
    <title>The Great Gatsby</title>
    <author>F. Scott Fitzgerald</author>
    <genre>Fiction</genre>
  </book>
  <book>
    <title>The Biggest Dilemma</title>
    <author>George Orwell</author>
    <genre>Dystopian</genre>
  </book>
</bookstore>

如果我们想选择“The Biggest Dilemma”这本书的“title”元素的所有祖先,我们可以使用以下祖先轴方法:

//title[text() = 'The Biggest Dilemma']/ancestor::*

下列的

下列轴方法选择当前节点结束标记之后的所有节点。此方法不考虑其目标节点的层次结构或位置。例如,如果XML文档或网页包含多个部分,您可以识别出现在特定部分之后的元素,而无需遍历整个树结构。

父级

XPath中的父级轴方法选择当前节点的父节点。您可以使用以下路径来定位父节点:

//标签名[@属性="值"]/parent::父标签名

当当前节点的子元素具有您可以轻松找到的唯一属性,而您想要验证父元素时,此方法尤其有用。

子级

XPath中的子级轴方法选择当前节点的所有子节点。它仍然是最常用的XPath轴方法之一,因为它有助于选择特定元素的子节点。

考虑以下代码:

<section id='text'>
    <p>Paragraph one</p>
    <p>Paragraph two</p>
    <p>Paragraph three</p>
    <p>Paragraph four</p>
</section>

我们可以使用以下轴来定位代码中的所有“p”元素:

//section[@id='text']/child::p

常见问题解答

为什么使用XPath而不是CSS选择器?

CSS选择器只能根据元素的ID、标签名和类名查找元素。而XPath允许您根据元素的位置、文本内容以及HTML结构中的其他属性来定位元素。此外,您可以将XPath表达式存储在变量中,并在应用程序中重复使用。

Selenium中的XPath支持哪些语言?

您可以将XPath与支持Selenium的任何编程语言一起使用。包括JavaScript、Java、Python、Ruby、C#和PHP。

XPath有哪些替代方案?

您可以使用CSS选择器、图像识别或Selenium的内置定位器作为XPath的替代方案。CSS选择器是最常见的一种,您可以使用标签名、ID或类名来查找元素。图像识别允许您根据图像定位元素。Selenium的内置定位器设计得简单易用。

结论

现在,您已经掌握了如何在Selenium中定义XPath、区分绝对XPath和相对XPath,并使用不同的XPath定位器来定位元素。定位器的选择将取决于内容的性质和您的最终目标。

如果您想在下一次面试中脱颖而出,请查阅我们关于Selenium面试问题的文章。