跳到内容

如何在 Selenium 中通过 XPath 查找元素(综合指南)

作为拥有 5 年以上经验的 Web 抓取和代理专家,我发现 XPath 是用于定位 Web 元素的最有用和最通用的技术之一。掌握 XPath 选择器可以帮助您从最复杂的网页中精确提取数据。

在这份包含 3200 多个单词的综合指南中,我将分享我所学到的有关在 Selenium 中使用 XPath 查找元素并与元素交互的所有知识。

XPath 到底是什么?

在我们深入使用之前,了解 XPath 的实际含义非常重要。

XPath 代表 XML 路径语言。它是一种用于从 XML 文档中选择节点的查询语言。本质上,XPath 提供了一种用于描述 XML 结构各部分的语法。

由于 HTML 的结构类似于 XML,并且元素像开始和结束标记一样嵌套,因此 XPath 也可用于定位 HTML 文档的某些部分。

根据 w3schools 的说法,有关 XPath 的一些关键事实:

  • XPath 使用路径表达式来选择 XML 文档中的节点或节点集
  • 这些路径表达式看起来非常类似于您在使用传统计算机文件系统时看到的路径表达式
  • XPath 包含 100 多个内置函数来操作字符串、数字、布尔值、节点集等。
  • XPath 是 XSLT(可扩展样式表语言转换)的主要元素

总之,XPath 是一种功能强大的查询和提取语言,专为导航 XML 文档而设计。

XPath 与 Selenium 有何关系?

Selenium 是一个用于控制 Web 浏览器的自动化框架。当您在 Selenium 中加载网页时,HTML 内容会被解析为 DOM(文档对象模型)结构。

DOM 将页面直观地表示为嵌套 HTML 元素的树。

XPath 可用于遍历 DOM 以查找页面上的特定元素并与之交互。

例如,考虑这个简化的 HTML:

<html>
<body>

  <div>
    <p>Hello World!</p>
  </div>

  <div>
    <img src="logo.png"/>
  </div>

</body>
</html>

DOM 可能看起来像这样:

       html
       /  \
     body   
     / \     
    div  div
      |    |
     p    img

然后,您可以使用 XPath 表达式来查询此结构中的元素:

/html/body/div[1]/p
//div/img

这使得 XPath 对于使用 Selenium 自动执行页面特定部分的操作非常有用。

XPath 语法基础知识

现在您已经了解了 XPath 的作用,让我们深入研究一下语法。

XPath 使用路径表达式来选择 XML 文档中的元素和属性。这些表达式看起来与计算机上的文件系统中的路径非常相似:

/Users/jsmith/Documents/letter.docx

正斜杠 / 向下导航嵌套文件夹。

一些基本的 XPath 模式:

  • nodename – 选择名称为nodename的所有节点
  • / – 从根节点选择
  • // – 选择任意深度的节点
  • . – 选择当前节点
  • .. – 选择父节点
  • @ – 选择属性

例如:

/html/body/div - Selects all div tags under body
//div - Selects all div tags anywhere 
div[@class=‘header‘] - Selects div tags with matching class attribute

我们将在本指南中介绍许多更专业的语法。但这些基本模式允许您开始制作有针对性的 XPath 选择器。

根据我的经验,只需掌握 5-10 个基础 XPath 表达式即可让您在大多数网站上定位元素。

查找网页元素 find_elementfind_elements

Selenium 提供了两种使用 XPath 定位元素的主要方法:

  • find_element() – 返回与 XPath 匹配的单个 WebElement
  • find_elements() – 返回所有匹配的 WebElement 的列表

这是一个简单的用法示例:

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

driver = webdriver.Chrome()
driver.get("https://www.example.com")

# Find single element
element = driver.find_element(By.XPATH, ‘//img‘) 

# Find multiple elements 
elements = driver.find_elements(By.XPATH, ‘//div‘)

通过这两种方法,您可以开始利用 XPath 的强大功能以自动方式与网页的特定部分进行交互。

查找元素的技巧

根据我多年的经验,以下是构建 XPath 选择器时的一些关键技巧:

  • 检查 HTML 源代码 – 通过查看原始 HTML 内容,您可以识别目标元素的独特属性和模式。所有现代浏览器都有用于查看源代码的开发人员工具。

  • 在浏览器中复制 XPath – 大多数浏览器开发工具还包括复制元素的完整 XPath 的功能。然后,您可以调整和简化这些基线选择器。

  • 专注于身份识别 – 页面元素的 id 属性提供了最直接和唯一的选择器,例如 //input[@id=‘search‘].

  • 课程帮助 – 类属性允许更灵活的查询,例如 //div[@class=‘results‘] 即使不完全独特。

  • 避免索引 – 建立对 [1]、[2] 等位置索引的依赖会导致定位器脆弱。

  • 越短越好 – 具有最少嵌套步骤的简洁 XPath 有助于避免缓慢的查询或不正确的匹配。

掌握这些准则将帮助您构建健壮的 XPath 选择器,以优雅地定位所需的页面元素。

常见的 XPath 模式和配方

现在您已经了解了基础知识,让我们看一下 XPath 模式的一些常见示例:

按属性值选择

//input[@type=‘submit‘]
//a[@href=‘contact.html‘]

部分属性匹配

//input[contains(@name, ‘search‘)]
//div[starts-with(@class, ‘result‘)]

选择文本匹配

//p[text()=‘Hello World‘] 
//h2[contains(text(), ‘Welcome‘)]

选择儿童

/div/p
//tbody/tr/td

索引选择

(//input[@type=‘button‘])[2]

链式选择

//div[@id=‘nav‘]/ul/li/a 

关注兄弟姐妹

//h1[text()=‘Articles‘]/following-sibling::p

我建议熟悉这些常见技术。它们形成了一个 XPath 技能工具包,可以在构建强大的查询时为您提供良好的帮助。

抓取示例

让我们看一下在 Python 中使用 Selenium 和 XPath 的示例网页抓取脚本。

我们将从电子商务网站提取产品数据:

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

# Initialize driver 
driver = webdriver.Chrome(‘/path/to/chromedriver‘)

# Load page
driver.get(‘https://www.example.com‘)

# Click shop link
shop_link = driver.find_element(By.LINK_TEXT, ‘Shop‘)
shop_link.click()

# Wait for new page to load
time.sleep(5)  

# Extract product details
product = driver.find_element(By.XPATH, ‘//div[@class="product"][1]‘)
name = product.find_element(By.XPATH, ‘.//h2‘).text
description = product.find_element(By.XPATH, ‘.//p‘).text 
price = product.find_element(By.XPATH, ‘.//span[@class="price"]‘).text

print(name, description, price)

# Close browser
driver.quit()

这演示了如何使用 XPath 精确定位元素以抓取嵌套页面数据。

常见问题和解决方案

以下是在 Selenium 中使用 XPath 定位器时可能出现的一些常见问题以及缓解策略:

超时时间

如果页面加载需要时间,请使用隐式和显式等待:

from selenium.webdriver.common.by import WebDriverWait 

driver.implicitly_wait(10) 

WebDriverWait(driver, 20).until(expected_conditions)

陈旧元素

如果 DOM 发生变化,请重新定位元素以避免陈旧元素异常:

elements = driver.find_elements(By.XPATH, ‘//div‘)
# DOM updates, elements now stale
elements = driver.find_elements(By.XPATH, ‘//div‘) 

浏览器兼容性

某些高级 XPath 功能可能无法在所有浏览器上运行。测试行为并根据需要进行简化。

性能慢

非常复杂的 XPath 表达式可能会减慢测试执行速度。尽可能简化结构。

提升品牌曝光性

匹配的元素不一定是可见的。确保它们在交互之前显示。

经验有助于预测这些问题——随着时间的推移,它们会变得更容易处理。

XPath 替代方案

虽然 XPath 很强大,但它并不总是最好的解决方案。以下是一些常见的替代方案:

CSS 选择器

CSS 选择器提供了一种简单、熟悉的方式来查找元素:

driver.find_element(By.CSS_SELECTOR, ‘input[type="submit"]‘)
driver.find_element(By.CSS_SELECTOR, ‘.search-box‘) 

ID 和名称属性

如果 ID 或名称确实唯一,请使用:

driver.find_element(By.ID, ‘search‘)
driver.find_element(By.NAME, ‘query‘) 

链接文本

匹配完整链接文本可以避免复杂的查询:

driver.find_element(By.LINK_TEXT, ‘Logout‘)

根据您的具体需求评估每个选项。我经常发现 XPath、CSS、ID 和链接文本定位器的组合可以提供最大的稳健性。

定位策略比较

以下是 XPath 与一些常见替代元素定位策略的比较:

付款方式例如:优点缺点
XPath的//div/p非常灵活的查询复杂的语法
CSS选择器div.结果 p熟悉的语法仅针对类/id/属性
ID#注册表单非常快速且独特需要 ID
名字名称=查询独特依赖命名约定
链接文字退出简单的链接仅适用于链接文本

正如您所看到的,每种策略都有权衡。将 XPath 与 CSS 选择器和属性一起使用可以提供强大的定位器灵活性。

lxml 和 parsel 的高级用法

虽然 Selenium 具有非常方便的内置查找方法,但 lxml 和 parsel 等专用解析库为复杂的抓取任务提供了额外的功能。

这些库提供强大的 XPath 支持以及许多其他功能,例如:

  • 快速 HTML 和 XML 解析器
  • 支持 XPath 1.0 和 2.0+
  • 广泛的 XPath 函数和运算符
  • 用于解析 HTML 的便捷绑定
  • 与 Scrapy 等流行框架集成

一些示例用法:

from lxml import html

tree = html.parse(‘page.html‘)
p_elements = tree.xpath(‘//p‘)

from parsel import Selector
sel = Selector(text=html_text)
links = sel.xpath(‘//a/@href‘).getall() 

对于较繁重的抓取工作,我经常使用这些库来补充 Selenium 的内置功能。

结论和主要教训

对于任何使用 Selenium 进行测试自动化或网页抓取的人来说,通过 XPath 查找元素是一项基本技术。

以下是我在 5 年多的利用 XPath 与复杂网站交互的过程中学到的一些重要经验教训:

  • 首先学习一些核心 XPath 模式,例如属性匹配、文本选择、子选择等。大多数用法都建立在这些基础知识之上。

  • 在简洁但独特的查询之间取得平衡需要练习。它既是一门艺术,也是一门科学。

  • 熟悉用于检查源代码和复制初始 XPath 字符串的浏览器开发人员工具。

  • 在适当的时候用 CSS 选择器和 id/name 属性补充 XPath。组合方法可以实现最大的鲁棒性。

  • 考虑使用 lxml 和 parsel 等高级 XPath 解析库,以增强 Selenium 之外的抓取功能。

  • 通过经验,学习预测和处理常见问题,例如陈旧元素和超时。

我希望本指南能够为释放 Selenium XPath 元素选择的强大功能提供全面的参考。如果您还有其他具体问题,请告诉我!

标签:

加入谈话

您的电邮地址不会被公开。 必填带 *