/ |
从根节点开始的绝对路径 |
/html/body(从到)
|
// |
任意位置的相对路径 |
//div(找所有div元素) |
. |
当前节点 |
./p(找当前节点下的p元素) |
.. |
父节点(当前元素的上一级) |
../a(找当前节点的父节点下的a元素) |
@ |
选择属性 |
//a[@href](找带href的链接) |
举个我自己的例子:之前爬知乎“热榜”,要提取每个热榜问题的标题和链接。用//div[@class='HotItem-title']/a
找标题链接,用//div[@class='HotItem-title']/a/text()
找标题文字——这样既拿到了链接(属性),又拿到了文字(文本),完美解决需求。
Xpath必学的进阶技巧:解决90%的“复杂提取”问题
基础语法会了,再学几个“进阶技巧”,能搞定你遇到的“疑难杂症”——比如“找某个元素后面的兄弟元素”“模糊匹配带变量的属性”“去掉文本里的空格”。
轴语法:找节点的“亲戚”
轴语法是Xpath的“高级搜索”,核心是“找节点周围的元素”。我用“亲戚关系”给你翻译一下:
parent::
:父节点(爸爸),比如//div[@class='answer']/parent::div
找回答节点的父容器;
child::
:子节点(儿子),比如//div[@class='answer']/child::p
找回答节点下的段落;
following-sibling::
:后面的兄弟节点(弟弟),比如//div[@class='answer']/following-sibling::div[@class='comment']
找回答节点后面的评论容器;
preceding-sibling::
:前面的兄弟节点(哥哥),比如//div[@class='comment']/preceding-sibling::div[@class='answer']
找评论对应的回答节点。
我之前爬知乎回答的时候,要找每个回答下面的“评论数”,就用了//div[@class='AnswerCard']/following-sibling::div[@class='CommentSection']//span[@class='CommentCount']
——翻译过来就是“找到回答卡片,再找它后面的评论区,最后找评论区里的评论数”。这个语法帮我精准提取了1000多条回答的评论数,没漏一个。
运算符:解决“模糊匹配”和“多条件筛选”
你有没有遇到过这种情况?要找的元素class不是固定的,比如淘宝商品价格有的是class='price'
,有的是class='price-red'
,或者链接里带“product”但参数不固定?这时候运算符就派上用场了。
最常用的三个运算符:
contains():模糊匹配属性值,比如//span[contains(@class,'price')]
找class包含price的span(不管是price还是price-red都能找到);
and/or:多条件叠加,比如//a[contains(@href,'product') and @class='title']
找href包含product且class为title的链接;
text():精确匹配文本,比如//p[text()='苹果手机']
找文字为“苹果手机”的段落。
我朋友做电商爬虫时,用//a[contains(@href,'item')]
爬淘宝商品链接——因为淘宝商品链接都带“item”参数,不管后面的数字怎么变,用contains()就能全覆盖。之前他用精确匹配@href='https://item.taobao.com/item.htm?id=123456'
,结果每个商品都要改一次,现在用contains()直接“一劳永逸”。
小技巧:去掉文本里的空格
你有没有遇到过提取的文本里全是空格或换行符?比如//p/text()
提取出来是“ 苹果手机 ”(前后有空格),这时候用normalize-space()函数就能“clean”掉多余空格://p[normalize-space(text())='苹果手机']
——这样就能精准找到文字为“苹果手机”的段落,不管前后有没有空格。我之前爬京东评价的时候,好多用户评论里带换行和空格,用这个函数才拿到“干净”的文字。
最后:给Xpath新手的3个“避坑提醒”
别用“”通配符滥竽充数://
是找所有元素,但会爬一堆无关内容,除非你真的要“所有元素”,否则别用;
避免“索引”依赖:比如//div[1]
是找第一个div,但页面结构一变,索引就错了,尽量用@id
或@class
定位;
用工具验证语法:推荐用Chrome的“检查”工具——按F12打开开发者工具,选中元素右键“Copy”→“Copy Xpath”,能快速生成语法,再根据需求调整(比如把绝对路径改成相对路径)。
我之前帮朋友爬拼多多商品数据,一开始用Chrome生成的绝对路径,结果拼多多页面一更新就失效;后来把/html/body/div[3]/div[2]/div[1]/h1
改成//div[@class='goods-title']
,才终于稳定——工具生成的语法是“参考”,不是“标准答案”,得根据实际情况调整。
其实Xpath没那么难,关键是“用对规则解决具体问题”。你要是按我上面说的试了,比如用//
相对路径爬页面,用contains()
解决模糊匹配,或者用轴语法找兄弟元素,欢迎回来告诉我效果!要是还有没搞懂的地方,也可以在评论区问我——我帮你一起想想办法。
对了,要是你想深入学Xpath,可以看看W3C的官方文档(XPath 1.0 规范),虽然有点枯燥,但权威性没话说。
绝对路径和相对路径有什么区别?该优先用哪个?
绝对路径是从页面根节点()开始的精确路线,比如/html/body/div[1]/p,就像从小区门口走到家,每一步都不能错,但动态页面结构一变就失效——我之前爬京东商品名称用/html/body/div[3]/div[2]/div[1]/h1,结果页面层级调整直接罢工;相对路径用//开头,不管页面结构怎么变,只要元素符合条件就能找到,比如//div[@id=’productTitle’],稳定多了。优先用相对路径,除非你100%确定页面结构永远不变。
遇到class不固定的元素,怎么用Xpath找?
用contains()函数模糊匹配属性值就行。比如淘宝商品价格有的class是price,有的是price-red,用//span[contains(@class,’price’)]就能把这两种都找到;要是链接里带固定关键词比如product,用//a[contains(@href,’product’)]也能匹配到带这个关键词的所有链接。
想找某个元素旁边的兄弟元素,Xpath怎么写?
用轴语法里的following-sibling::(找后面的兄弟)或preceding-sibling::(找前面的兄弟)。比如我之前爬知乎回答找评论区,用//div[@class=’AnswerCard’]/following-sibling::div[@class=’CommentSection’],就是先找回答卡片,再找它后面的评论区容器;反过来想找评论对应的回答,用preceding-sibling::就能定位到前面的回答节点。
提取的文本有多余空格或换行,怎么用Xpath清理?
用normalize-space()函数,比如//p[normalize-space(text())=’苹果手机’],能自动清理文本前后的多余空格和换行。我之前爬京东用户评价时,好多评论带换行和空格,用这个函数就拿到了干净的文字内容。
用Xpath有什么常见坑要避开?
别用通配符滥竽充数,比如//会爬一堆无关元素;别依赖元素索引比如div[1],页面结构一变就错;Chrome工具生成的Xpath是参考,要改成相对路径——比如我用Chrome生成的绝对路径爬拼多多商品,结果页面更新直接失效,改成//div[@class=’goods-title’]才稳定。