写爬虫的朋友,估计都遇到过这种糟心事儿:本来想抓个商品价格,结果爬回来一堆乱七八糟的广告;更坑的是,好不容易写好的代码,没跑两天,网站一改版,所有选择器全失效,白忙活一场。
其实不用愁,这种时候,XPath就能救场——它就是专门用来精准定位网页元素的“神器”。

先给大家讲个我自己的真实经历
上个月,我想爬一个电商网站的商品信息,一开始用CSS选择器写了几行代码,试了试,能正常运行,数据也顺利抓下来了,当时还挺开心。
结果呢?才过了三天,网站前端改了个版,我再运行代码,直接报错,啥数据都抓不到了。后来一查才知道,原来网页里表示价格的类名,从“.price”改成了“.sale-price”——就因为一个名字的变化,我之前写的代码全废了。
你们是不是也遇到过这种情况?真的特别让人崩溃。
后来我就换成了XPath,不再盯着类名、ID这些容易变的东西,而是根据价格在页面里的位置特征来定位,比如“商品详情页右边那个红色的数字”。
别说,还真管用!哪怕页面再改样式,只要整体结构没大变动,XPath依然能精准找到我要的元素。
这就是XPath最牛的地方:它不依赖你给元素起的类名或者ID,只看这个元素在网页文档里的“地址”和“亲戚关系”,不容易失效。
XPath到底是什么?一句话给你说透
咱们把HTML网页想象成一棵大树就好理解了:最外层的<html>是树根,里面的<head>和<body>是树干,而那些<div>、<p>、<a>标签,就是树上的树枝和树叶。
XPath呢,就是一套“找树叶”的语言——告诉你怎么从树根出发,一步步找到你想要的那片“叶子”(也就是网页元素)。
举个例子,有这么一段XPath:`/html/body/div[2]/p[1]/text()`
翻译成人话就是:从网页最根上开始,先找到body,再找到里面的第二个div,然后取这个div里的第一个p标签,最后把p标签里的文字拿出来,就这么简单。
常用写法,记住这几种就够⽤,不用死记硬背
1. 绝对路径(不推荐)
比如:`/html/body/div[1]/div[2]/a`
这种写法太死板了,就像一张手写的寻宝地图,一步都不能错。网页稍微改个层级,比如多套一个div、少一个div,这个路径就失效了,新手千万别一开始就用这个。
2. 相对路径(强烈推荐,灵活又好用)
比如:`//div[@class='price']/text()`
开头的`//`特别关键,意思是“从网页任何位置开始找”,不用从头一步步数层级,灵活多了,大部分时候用这个就够了。
3. 按属性筛选(最常用的场景)
比如找用户名输入框:`//input[@id='username']`
找指定链接:`//a[@href='https://example.com']`
还能多条件筛选,比如找类名为product、且数据类型是book的div:`//div[@class='product' and @data-type='book']`
4. 按文本内容找(CSS做不到的功能)
比如:`//button[contains(text(), '登录')]`
意思就是:只要按钮上的文字里包含“登录”两个字,不管它的类名、ID是什么,都能找到。这个在对付多语言网站的时候,特别好用。
5. 按位置索引(找第几个元素超方便)
`//ul/li[1]` —— 找ul标签里的第一个li
`//ul/li[last()]` —— 找ul标签里的最后一个li
`//ul/li[position()<3]` —— 找ul标签里的前两个li
实战演示:从知乎首页抓问题标题
咱们打开知乎首页,按F12打开开发者工具,看一下问题标题的元素结构,大概是这样的:
<h2 class="QuestionTitle">
<a>你写过哪些实用的Python代码?</a>
</h2>
如果用CSS选择器,写法是:`.QuestionTitle a`
用XPath的话,就是:`//h2[@class='QuestionTitle']/a/text()`
但你们想过没有,如果知乎改版,把class名改成“ZhihuQuestionTitle”,CSS选择器就废了,但XPath可以这么写:`//h2[contains(@class, 'Title')]/a/text()`
翻译过来就是:只要是h2标签,它的class里包含“Title”这三个字母,不管你怎么改类名,我都能找到它——这就是XPath的灵活性!
一个小技巧,让你的爬虫更稳,少踩坑
重点来了:别用完整的绝对路径,多用电`//`和`contains()`,这俩组合起来,能避开很多改版的坑。
举个例子,你想抓某网站的文章正文,一开始可能找到的路径是:`//div[@id='article']/div[@class='content']/p`
但如果有一天,网站在article和content之间,多套了一层div,你的XPath就失效了。
改成这样就稳了:`//div[@id='article']//p`
中间的`//`表示“中间可以跳过任意层级”,不管它在article里面套多少层div,所有的p标签(也就是正文内容)都能抓到,再也不怕网站小改版了。
XPath和CSS选择器,到底该用哪个?别纠结
很多新手都会纠结,到底选哪个,其实很简单,看场景来选就好,给大家整理好了:
| 使用场景 | 推荐选择 |
|---|---|
| 根据id或class快速定位元素 | CSS选择器(更快、写法更简洁) |
| 根据文本内容找元素(比如找“登录”按钮) | XPath(CSS根本做不到) |
| 需要向上找父元素 | XPath(CSS做不到) |
| 网页结构不稳定,但元素特征稳定(经常改版) | XPath |
| 做大规模爬虫,对性能要求高 | CSS选择器(一般比XPath快10-20%) |
两个新手必踩的坑,提前避开,少走弯路
坑一:索引从1开始,不是0!
这是最容易出错的地方!咱们写Python、Java的时候,索引都是从0开始,但XPath不一样,`//div[1]`指的是第一个div,不是第二个。很多新手一开始都会写错,记牢这一点,能省很多麻烦。
坑二:小心命名空间的坑
有些网页会用XML命名空间,标签会变成<x:div>这种样子,这时候如果直接写`//div`,是匹配不到的。正确的写法是`//*[local-name()='div']`,这样就能忽略命名空间,正常匹配到div标签了。
总结
其实XPath的学习成本真不高,不用死记硬背所有语法,记住上面说的几种常用写法和避坑技巧,就能应对大部分爬虫场景。
而且一旦你掌握了它,就会发现,很多CSS选择器搞不定的难题,它两三行代码就能解决。尤其是爬那些经常改版、页面结构杂乱的网站时,XPath绝对是你的救命稻草。
你可以把它想象成一个“能听懂人话”的定位系统——你跟它说“找那个价格旁边的红色按钮”,它就能精准给你找出来,不用你一点点去抠标签、抠类名。
下次写爬虫,不妨试试用XPath来写定位,你会发现,原来网页元素不是杂乱无章的,而是一棵能按图索骥的树,抓数据也会变得简单又高效。
