爬虫Xpath语法详解

xpath是定位dom元素非常直观的方法之一,在爬虫中的使用尤其常见。

绝对路径和xpath

关于html的dom树这里就不赘述了,相信根节点,子节点,兄弟节点这些概念大家也都听的很多。

在一棵dom树里面,想定位某个元素有绝对路径和xpath的区分。如下图所示,选择了一个img标签以后点击右键,可以选择是复制xpath还是完整的路径

1-path.png

如果是绝对路径结果是这样的

/html/body/div[3]/div[2]/div/div[1]/div[1]/div[2]/div/div/ul[2]/li[1]/div[1]/a/img

从根节点开始一级一级往下,一直到img元素,每一层都被罗列了出来。真正在程序中这样子获取元素会非常麻烦,也没有必要。

如果是xpath结果是这样的

//*[@id="content"]/div/div[1]/div[1]/div[2]/div/div/ul[2]/li[1]/div[1]/a/img

虽然还是不够简洁,但是已经能看出比完整路径要好一点了。

当然,默认的xpath还是不够言简意赅一目了然,大多数时候我们还是需要通过xpath语法去构建自己的xpath来定位元素

浏览器自带的xpath工具

浏览器已经为我们准备好了xpath验证工具,这样我们就可以一边修改一边验证,在网页中确认可以定位到元素了再放进我们的程序里。

这里以chrome为例,有两种方法可以验证我们写的xpath。

在开发者模式中,首先是可以通过在Element页签使用Ctrl+f打开搜索框,在里面通过xpath来查找元素

2-search.png

如上图所示,通过xpath找到了两个alt属性为项塔兰的img元素。

然后可以进入console,通过$x()语法来验证

3-console.png

网页可能自带很多错误信息,console中可以通过clear()进行清除

如上图所示,找到了3个alt属性为鸳鸯六七四的img元素,点击其中任意一个找到的元素都会自动跳转到element的对应位置。

xpath语法

下面开始正式进入xpath的语法说明。

常用符号

xpath基本就是下列常用符号的组合和级联

符号说明举例
/表示从root开始查找,或者表示子节点/html/body/div
//表示从任意层级开始查找//div
*通配符,表示任意元素
@获取属性//img[@alt=‘xxx’]
.当前层级或当前节点
上一层级或父节点//div/…/img

定位元素

xpath的常用格式如下,通过不断级联向更深层次去定位,其中路径如果省略默认就是root

路径(/或者//)元素名称[@属性名=xxx]

例如//img[@alt='鸳鸯六七四']就表示从任意层级开始查找,需要找的元素是img,需要满足的条件是alt属性值为"鸳鸯六七四"。

需要注意的是根据属性值来定位,属性值必须加上引号,单引号或者双引号都行。

除了利用属性值来定位,还可以通过是否具有某属性来定位。

//img[@alt]

上面的表达式表示从任意层级开始查找,找到含有alt属性的img元素,范围就比上面宽了很多。

如果不确定元素名称就可以用通配符来代替

//*[@id='content']

上面的表达式表示从任意层级开始查找,找到id为content的那个元素。

有的元素的属性很长,或者包含多个值,例如<ul class='list-col list-col5 list-express slide-item clone'></ul>这时候用//ul[@class='list-express']是无法定位该元素的,必须要么用完整的值,要么像下面这样获取部分值

//ul[contains(@class,'list-express')]

当然除了通过属性,还可以通过文字内容进行定位text()string()都表示元素包含的文字内容,区别是前者不能包括子元素,后者则是所有子元素的文字内容之和。

例如下面这个就可以识别出<img><a>鸳鸯六七四</a></img>

//*[string()='鸳鸯六七四']

但是下面这个就只能识别出<img>鸳鸯六七四</img>

//*[text()='鸳鸯六七四']

既然是文字就有可能有一大段,所以可以对文字进行部分匹配

//a[contains(string(),'鸳鸯')]
//a[starts-with(string(),'鸳鸯')]

上面两种分别是包含“鸳鸯”两个字的和以“鸳鸯”两个字开头的文字内容。

多重定位

当然通常不会是直接就能一步到位找到想要的那个元素,而要么是先找到容易定位的上层元素,又或者是找到了很多同类型的元素需要去进行筛选。这时候只需要将前面找到的xpath元素做为root级联下一个xpath规则即可。

//div[@class='info']//a[starts-with(string(),'鸳鸯')]

上面这个表达式表示首先找到符合条件的div元素,然后在该元素内部任意层次查找符合条件的a元素

//div[@class='info']/a[starts-with(string(),'鸳鸯')]

将双斜线换成单斜线,就是从div元素内部的下一层级查找a元素。

这种级联关系可以一直持续,直到找到最终元素为止,下面是几种特殊情况。

同级元素,需要借助..符号

//div[@class='info']/../div[@class='cover']

索引位置查找,可以用中括号加数字。注意这里分为两类,同类元素在同一元素下和不在同一元素下。

(//ul[contains(@class,'list-express')])[2]

上面是不在同一元素下的情况,查找到的多个ul在不同的层次,所以要对前面整个内容加上小括号表示整体。

(//ul[contains(@class,'list-express')])[2]/li[2]

如果继续在ul下面查找li,这些li都在同一个ul元素下,所以可以直接用中括号加数字。

不管哪种方式都要注意,xpath的索引是从1开始,不是0!

如果不确定是第几个元素,可以用一些关键字来辅助,例如最后一个元素

(//ul[contains(@class,'list-express')])[2]/li[last()]

或者倒数第二个元素

(//ul[contains(@class,'list-express')])[2]/li[last()-1]

多条件组合

还可以通过逻辑运算符号andor来进行多条件组合定位

//span[contains(@class,'allstar') and contains(@class,'star-img')]
//span[contains(@class,'allstar') or contains(@class,'star-img')]

获取属性或文字

定位到了元素,最终目的还是获取元素的属性值或者是文字内容。

text()获取文字内容

//span[@class='average-rating']/text()

@获取属性值

//img/@src

需要注意的是,查找出来的文字内容还是xpath对象,并不是字符串

xpath在爬虫中的使用

下面以获取京东商城商品图片为例来进行演示,演示环境为python3,使用scrapy框架。

图片的dom信息如下图所示

4-jd.png

整个列表在一个div下,然后每个item有一个div用来存放img信息。

首先通过class名字可以唯一定位到整个列表

itemList = response.xpath('//div[@class="search_prolist_item"]')

之后通过for循环获取单个item中的img信息

for node in itemList:
    item = JdItem()
    item['img_url'] = node.xpath('.//div[@class="search_prolist_cover"]/img[@class="photo"]/@src').extract()[0]
    ...
    ...

这里首先定位到包裹img的div,然后是img,最后获取img的src属性。注意提取出来的src文字还是xpath对象,需要使用extract()方法来转为python的字符串,而且还需要注意,即使只找到了单个元素,scrapy的xpath对象还是会返回一个list,需要取出元素再使用。

我是T型人小付,一位坚持终身学习的互联网从业者。喜欢我的博客欢迎在csdn上关注我,如果有问题欢迎在底下的评论区交流,谢谢。

  • 25
    点赞
  • 184
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值