如果您希望使用 Python 从网页中提取数据,XPath 是您的网页抓取工具包中必不可少的工具。 XPath 提供了一种浏览页面 HTML 结构并精确定位所需元素和数据的方法。
在本指南中,我们将介绍 XPath 的基础知识,并演示如何利用它的强大功能通过 Python 进行网页抓取。最后,您将准备好使用 XPath 来处理各种抓取任务,以手术方式提取您想要的数据。
什么是XPath?
XPath 代表 XML 路径语言。它是一种用于从 XML 或 HTML 文档中选择节点的查询语言。使用 XPath,您可以指定一个与文档结构匹配的模式,它将返回与该模式匹配的所有元素。
虽然 XPath 最初是为 XML 设计的,但它也可以与 HTML 配合使用,这使其成为 Web 抓取的理想选择。它为 CSS 选择器或正则表达式提供了更强大、更灵活的替代方案。
XPath 语法基础知识
要开始使用 XPath,您需要了解 XPath 语法的构建块。以下是关键概念:
按标签名称选择节点
最基本的 XPath 表达式就是简单地指定一个标签名称。例如:
//h1
选择所有<h1>
页面上的标题元素//p
选择所有<p>
段落元素//img
选择所有<img>
图像元素
按属性选择节点
您可以使用以下方法选择具有特定属性或属性值的元素 @
句法:
//*[@class="highlighted"]
选择具有“highlighted”类的所有元素//a[@href]
全选<a>
具有 href 属性的锚元素//img[@alt="Logo"]
选择<img>
替代文本为“Logo”的元素
按位置选择节点
您可以使用方括号根据节点的位置选择节点 []
和一个数字索引:
//ul/li[1]
选择第一个<li>
每个内的项目<ul>
无序列表//table/tr[last()]
选择最后一个<tr>
每个中的行<table>
//ol/li[position() <= 3]
选择前三个<li>
每个中的项目<ol>
有序列表
按关系选择节点
XPath 允许您在文档树中上下导航,以根据祖先、后代、同级等选择元素:
//div[@class="content"]/*
选择的所有子元素<div>
具有“内容”类的元素//p/..
选择所有的父元素<p>
段落//h1/following-sibling::p
全选<p>
后面的兄弟元素<h1>
标题//section//img
全选<img>
作为 a 的后代的元素<section>
在任何级别
谓词和函数
XPath 支持广泛的谓词和函数,以进一步细化您的选择:
//p[contains(text(),"scrapy")]
选择<p>
包含文本“scrapy”的元素//a[starts-with(@href,"https")]
选择<a>
href 以“https”开头的元素//ul[count(li) > 10]
选择<ul>
包含超过 10 个的元素<li>
项目//img[string-length(@alt) > 0]
选择<img>
具有非空 alt 属性的元素
将 XPath 与 lxml 和 BeautifulSoup 结合使用
现在您已经了解了 XPath 语法的基础知识,让我们看看如何在 Python 中将其与流行的 lxml 和 BeautifulSoup 库一起使用。我们将演练一个从 ScrapingBee 主页抓取主标题文本的示例。
使用 lxml 和 BeautifulSoup 解析 HTML
首先,我们需要使用 requests 库获取网页的 HTML,并将其解析为可以使用 XPath 查询的树结构。我们将使用 BeautifulSoup 解析 HTML 和 lxml 来评估我们的 XPath 表达式:
import requests
from bs4 import BeautifulSoup
from lxml import etree
html = requests.get("https://scrapingbee.com")
soup = BeautifulSoup(html.text, "html.parser")
dom = etree.HTML(str(soup))
在这里,我们:
- 使用获取 HTML
requests.get()
- 使用 html.parser 将 HTML 字符串解析为 BeautifulSoup 对象
- 将 BeautifulSoup 对象转换为字符串,以便我们可以使用 lxml 解析它
etree.HTML()
功能 - 将字符串解析为 lxml
Element
我们可以使用 XPath 查询对象
构建和评估 XPath 表达式
现在我们有了一个已解析的 HTML 树,我们可以构造一个 XPath 表达式来选择主要内容 <h1>
页面标题:
heading_xpath = ‘//h1‘
为了根据我们解析的 HTML 文档评估这个 XPath,我们使用 xpath()
方法:
heading_elements = dom.xpath(heading_xpath)
dom.xpath()
调用将返回与我们的 XPath 选择器匹配的所有元素的列表。在这种情况下,应该只有一个匹配 <h1>
元件。
提取文本和属性
一旦我们引用了该元素,我们就可以使用 lxml 的属性轻松提取其文本和任何属性:
heading_text = heading_elements[0].text
print(heading_text)
# Tired of getting blocked while scraping the web?
我们仅用一行 XPath 就成功提取了标题文本!我们还可以使用以下方式访问元素的属性值 get()
:
heading_id = heading_elements[0].get(‘id‘)
将 XPath 与 Selenium 结合使用
另一种方法是使用 Selenium 来自动化和抓取需要 JavaScript 的动态网站。 Selenium 提供了自己的方法来使用 XPath 字符串选择元素。
配置 Selenium WebDriver
要开始使用 Selenium,您首先需要安装 Selenium 包和您要使用的浏览器的 Web 驱动程序。以下是配置 Chrome 驱动程序的方法:
from selenium import webdriver
from selenium.webdriver.common.by import By
driver_path = "/path/to/chromedriver"
driver = webdriver.Chrome(driver_path)
确保下载适合您的 Chrome 安装的 ChromeDriver 版本,并提供可执行文件的路径。
使用 XPath 查找元素
配置驱动程序后,我们可以导航到网页并开始查找元素。 Selenium 的 WebDriver 提供了 find_element
接受 XPath 定位器的方法:
driver.get("https://scrapingbee.com")
heading_xpath = "//h1"
heading_element = driver.find_element(By.XPATH, heading_xpath)
与 lxml 示例类似,这将找到第一个 <h1>
页面上的元素。如果您想查找与 XPath 匹配的所有元素,请使用 find_elements
代替:
paragraph_xpath = "//p"
paragraph_elements = driver.find_elements(By.XPATH, paragraph_xpath)
提取文本和属性
一旦获得了对 Web 元素的引用,您就可以访问其属性,例如文本内容和属性:
heading_text = heading_element.text
print(heading_text)
# Tired of getting blocked while scraping the web?
paragraph_id = paragraph_elements[0].get_attribute("id")
使用 Selenium 和 XPath 提取数据非常简单,但请记住,Selenium 通常比使用纯 HTTP 请求库慢,因为它运行实际的浏览器。
提示和最佳实践
当您开始使用 XPath 进行网页抓取时,请记住以下一些提示和技巧:
使用 Chrome DevTools 测试 XPath 表达式
构建 XPath 选择器时,以交互方式测试它们以确保它们符合您的期望非常有用。 Chrome DevTools 提供了一种简单的方法来做到这一点:
- 右键单击一个元素并选择“Inspect”以打开 DevTools Elements 面板
- 按 Ctrl+F 打开搜索框
- 输入 XPath 表达式以突出显示页面上的匹配元素
处理不一致的标记
野外网站通常具有不一致或损坏的 HTML 标记,这可能会导致您的 XPath 选择器出错。在使用 lxml 解析 HTML 之前,使用 BeautifulSoup 等库来清理和规范化 HTML 是个好主意。
编写健壮且可维护的 XPath
为了最大程度地减少由于目标站点上的布局更改而导致抓取工具损坏的可能性,请尝试编写尽可能具体的 XPath 表达式,但不要过于具体。优先选择语义属性(如标记名称、ID 和数据属性),而不是依赖标记的特定结构。
将复杂的 XPath 表达式分解为具有描述性名称的变量也是一个好主意,以提高可读性和可维护性。
缓存结果以提高性能
如果您要抓取大量数据或多次访问同一页面,请考虑缓存已解析的 HTML 和 XPath 结果,以避免不必要的网络请求和解析开销。您可以使用简单的字典或更强大的解决方案(例如 MongoDB 或 Redis)进行缓存。
结论
XPath 是一个极其强大的工具,用于从 HTML 页面中精确提取数据。通过对语法的基本了解以及将 CSS 选择器转换为其 XPath 等效项的能力,您可以处理各种 Web 抓取任务。
lxml、BeautifulSoup 和 Selenium 等 Python 库提供了将 XPath 集成到抓取工作流程中的简单方法。根据您的具体需求和目标站点的特征,您可以选择最有效的方法。
当您继续使用 Python 和 XPath 进行网页抓取之旅时,请始终确保遵守网站服务条款和 robots.txt 限制。请记住温习 XPath 函数和运算符的基础知识 - 您会惊讶地发现只需几行巧妙的 XPath 即可实现如此多的成果!