一、XPath 是什么?
XPath 是网页的“寻宝地图”,帮你在 HTML 里精准找到东西。想抓标题、价格或某个属性?XPath 就像指路说明,比如“从这层开始,找那个带特定标签的宝箱”。这次我们重点玩转 .(当前节点)、*(通配符)、@(属性)和字符串操作。
二、准备工作
-
工具:
- 用 Python 的 lxml 库跑 XPath。
- 安装:pip install lxml。
-
基础 HTML: 新建 sample.html:
<html>
<body>
<div class="shop">
<h1>小店</h1>
<p class="item" price="10">苹果</p>
<p class="item" price="5">香蕉</p>
</div>
</body>
</html>
三、核心用法:解锁 .、*、@ 和字符串
1. . —— “从我这开始找”
. 表示当前节点,像站在某个位置说“从我这往后看”。
from lxml import etree
tree = etree.parse("sample.html")
shop = tree.xpath('//div[@class="shop"]')[0] # 先定位到 shop
items = shop.xpath("./p") # 从 shop 开始找 p
for item in items:
print(item.text)
# 输出:
# 苹果
# 香蕉
- //div[@class=“shop”] 先找到 <div class=“shop”>。
- ./p 说“从当前 div 往下找所有 p”。
- 比喻:像在超市里站在“水果区”说“从这找所有水果”。
对比:不用 .,直接 //p 会找整个 HTML 的 p,可能抓到无关的。
2. * —— “啥都行,通配符”
* 是占位符,代表任意标签,像个“万能钥匙”。
all_elements = tree.xpath('//div/*') # div 下的任意子标签
for elem in all_elements:
print(elem.tag, elem.text)
# 输出:
# h1 小店
# p 苹果
# p 香蕉
- //div/* 找 div 下的所有子节点(h1、p 都行)。
- 比喻:像说“把货架上所有东西都拿来,不管啥种类”。
用法扩展:
- //*[@class=“item”]:找任何有 class=“item” 的标签,不限 p 或 div。
3. @ —— “我要标签上的小纸条”
@ 用来取属性值,像从标签上撕下“价格牌”。
prices = tree.xpath('//p[@class="item"]/@price')
for price in prices:
print(price)
# 输出:
# 10
# 5
- //p[@class=“item”]/@price 找 class 为 “item” 的 p 的 price 属性。
- 比喻:像问“这些商品的价格标签是多少”。
组合:
items = tree.xpath('//p[@class="item" and @price="10"]')
print(items[0].text) # 输出:苹果
- @price=“10” 加条件,找 price 等于 10 的。
4. 字符串操作 —— “找特定单词”
XPath 能处理文本,比如用 contains() 找含特定字符串的内容。
fruits = tree.xpath('//p[contains(text(), "果")]')
for fruit in fruits:
print(fruit.text)
# 输出:
# 苹果
- contains(text(), “果”) 找文本含“果”的 p。
- 比喻:像说“找所有名字带‘果’的东西”。
高级点:
cheap = tree.xpath('//p[string(number(@price)) < 10]')
print(cheap[0].text) # 输出:香蕉
- string(number(@price)) < 10 把 price 属性转数字比较。
- 比喻:像问“哪些东西价格低于 10 元”。
四、实战练习
试试这个 HTML:
<html>
<body>
<div id="market">
<span>商品</span>
<p class="goods" data-id="001">面包 - 8元</p>
<p class="goods" data-id="002">牛奶 - 12元</p>
</div>
</body>
</html>
任务:
- 从 market 开始找所有 p。
- 用通配符找 market 下的所有子节点。
- 提取所有 goods 的 data-id 属性。
- 找文本含“元”且价格小于 10 的商品。
答案:
from lxml import etree
tree = etree.parse("sample.html")
market = tree.xpath('//div[@id="market"]')[0]
# 1. 从 market 开始找 p
ps = market.xpath("./p")
for p in ps:
print(p.text)
# 输出:面包 - 8元、牛奶 - 12元
# 2. 通配符找所有子节点
all_kids = market.xpath("./*")
for kid in all_kids:
print(kid.tag, kid.text)
# 输出:span 商品、p 面包 - 8元、p 牛奶 - 12元
# 3. 提取 data-id
ids = tree.xpath('//p[@class="goods"]/@data-id')
print(ids) # 输出:['001', '002']
# 4. 找含“元”且价格小于 10
cheap = tree.xpath('//p[contains(text(), "元") and string(number(@data-id)) < 10]')
print(cheap[0].text) # 输出:面包 - 8元
五、注意事项
- . 用错:
- 忘了加 .,可能会找全文档,范围太大。
- * 滥用:
- //* 会抓太多东西,尽量限定范围。
- @ 属性不存在:
- 检查 HTML,确保属性拼写正确。
- 字符串复杂:
- contains() 区分大小写,注意文本格式。
六、总结:XPath 的寻宝秘籍
- .:从当前节点出发,像站定位置找。
- *:通配符,啥标签都行,像万能钥匙。
- @:取属性,像撕下标签看信息。
- 字符串:用 contains() 或 string() 玩转文本和数字。
通过这个教程,你应该能用 .、*、@ 和字符串操作,在 HTML 里找到任何“宝藏”!有问题欢迎随时私信交流。