miboy 发表于 2022-7-6 16:15

xpath终结者:xpath-helper-plus

本帖最后由 miboy 于 2022-7-6 16:17 编辑

### 前言

作为一个资深『xpath』提取工程师,想要快速从页面中拿到数据,肯定需要借助一些工具,
而最初接触的就是`xpath-helper`这块浏览器插件。使用一段时间后,发现笔者有一些特别的需求,想在此基础上扩展一下。
于是乎就学习了如何开发chrome插件?如何使用自己属性的vue来开发?经过双休一顿文档、gayhub了解之后,有了这样一款工具。

### 问题

xpath-helper2.0.2原生是支持按住shift后通过鼠标来定位选择元素,并输出xpath语法,但是这种方式出来的xptah语法并不友好。

比如说我想拾取掘金的某个文章标题:
![](https://miclon-job.oss-cn-hangzhou.aliyuncs.com/img/20220624142607.png)

> /html/body/div[@id='__nuxt']/div[@id='__layout']/div[@id='juejin']/div[@class='view-container container']/main[@class='container main-container with-view-nav']/div[@class='view timeline-index-view']/div[@class='timeline-container']/div[@class='timeline-content']/aside[@class='index-aside aside']/div[@class='signin-tip signin']/div[@class='first-line']/button[@class='btn signin-btn']/span[@class='btn-text']

它出来了一个xpath语法,这个xpath语法是从DOM根节点开始逐一向下(源码是从下至上)来拼接的。这样就会变成十分地冗余。
虽然它的确能够精准定位到我们想要的元素,但是一旦把这样的xpath语法复制到代码里,是十分可怕的。

当然还有一部分程序员热衷于选择使用chrome原生的元素复制成xpath。

![](https://miclon-job.oss-cn-hangzhou.aliyuncs.com/img/20220624142710.png)

出来的结果是:

> //*[@id="juejin"]/div/main/div/div/div/aside/div/div/button/span

显然以上两种方案都有其问题:语法冗余、毫无可读性。

### 解决

笔者给出的解决方案是在xpath-helper基础上,增加一个辅助功能,它可以最大化精简xpath语法,一旦发现其语法能够识别到该元素就不再继续往上查找。而是立刻返回。

![](https://miclon-job.oss-cn-hangzhou.aliyuncs.com/img/20220624143103.png)

> //span[@class='btn-text']

并且它也可以友好的转为css选择器语法:
> span.btn-text

我们可以在chrome的元素中检查这个语法:

- xpath:
![](https://miclon-job.oss-cn-hangzhou.aliyuncs.com/img/20220624143233.png)
- css:
![](https://miclon-job.oss-cn-hangzhou.aliyuncs.com/img/20220624143247.png)


### 实现

xpath-helper-plus其核心API均来自于xpath-helper。

笔者在此基础上增加了一些额外的功能,比如:精简xpath语句、转化CSS选择器。

与原有的xpath helper不同的是,这次chrome插件采用Vue3+vite来开发,面向组件,通过vite打包成chrome插件规范的文件目录结构。
未来可能会提供更多的功能。或者在此基础上开发其他插件。

### 开源

(https://github.com/mic1on/xpath-helper-plus)

如果你无法访问GitHub,提供给你离线的chrome插件安装包。

liesauer 发表于 2022-7-7 09:42

getstr88 发表于 2022-7-6 22:44
有点没理解。chrome中xpath的输出,如果能通过class id等唯一标识的,它也会从那里开始写。除非是没有的, ...

这个所谓的精简是有问题的,浏览器生成的路径肯定是唯一的,虽然长了点,但是总能给你找对(结构不变的情况下,不包含列表式增删),这是很稳定的行为。
但是楼主所谓的精简,用楼主提到的“//span[@class='btn-text']”举例,我一开始拿到的html当时可能只有一个span用到了这个类,然后给精简了最简的样子,但是网页内容要是动态滚动加载的,后面一加载新内容,又多了几个span,此时“//span[@class='btn-text']”就会匹配到多个。

大勹 发表于 2022-9-7 18:57

非常非常的 nice

就是有个疑问,在 dev 运行的时候,访问显示的访问地址,去访问的时候,会出现 这样的错误,
问题是怎么才能向网页一样,实时的热更新呢,感谢楼主大大
      
Uncaught TypeError: Cannot read properties of undefined (reading 'query')    utils.ts:3
    at sendMessageToContentScript (utils.ts:3:17)
    at watch.immediate (home.vue:15:3)
    at callWithErrorHandling (runtime-core.esm-bundler.js:155:22)
    at callWithAsyncErrorHandling (runtime-core.esm-bundler.js:164:21)
    at job (runtime-core.esm-bundler.js:1782:17)
    at doWatch (runtime-core.esm-bundler.js:1818:13)
    at watch (runtime-core.esm-bundler.js:1668:12)
    at setup (home.vue:13:1)
    at callWithErrorHandling (runtime-core.esm-bundler.js:155:22)
    at setupStatefulComponent (runtime-core.esm-bundler.js:7165:29)

sam喵喵 发表于 2022-7-6 16:23

感谢分享,期待更强大工具出现~

Xw丶小威 发表于 2022-7-6 17:39

可以的。方便很多。

kiopc 发表于 2022-7-6 19:12

不错,对爬虫来说很友好!
精简xpath语句是怎么实现的?思想是啥啊?

萌新与小白 发表于 2022-7-6 20:21

还有一个插件SelectorsHub,也可以测试xpath

E式丶男孩 发表于 2022-7-6 21:48

这东西挺好的啊

likoaong 发表于 2022-7-6 22:17

mac字体好看啊

不苦小和尚 发表于 2022-7-6 22:20

楼主,插件安装不了什么原因

不苦小和尚 发表于 2022-7-6 22:23

不苦小和尚 发表于 2022-7-6 22:20
楼主,插件安装不了什么原因


Invalid value for 'web_accessible_resources'.
无法加载清单。

miboy 发表于 2022-7-6 22:33

不苦小和尚 发表于 2022-7-6 22:23
Invalid value for 'web_accessible_resources'.
无法加载清单。

1是否已经在扩展中心-加载扩展文件夹
2加载后浏览器应该会出现插件logo
3打开百度后点开插件测试
页: [1] 2 3
查看完整版本: xpath终结者:xpath-helper-plus