您现在的位置是:网站首页> 编程资料编程资料
golang goquery selector选择器使用示例大全_Golang_
2023-05-26
399人已围观
简介 golang goquery selector选择器使用示例大全_Golang_
引言
最近研究Go爬虫相关的知识,使用到goquery这个库比较多,尤其是对爬取到的HTML进行选择和查找匹配的内容时,goquery的选择器使用尤其多,而且还有很多不常用但又很有用的选择器,这里总结下,以供参考。
如果大家以前做过前端开发,对jquery不会陌生,goquery类似jquery,它是jquery的go版本实现。使用它,可以很方便的对HTML进行处理。
基于HTML Element 元素的选择器
这个比较简单,就是基于a,p等这些HTML的基本元素进行选择,这种直接使用Element名称作为选择器即可。
比如dom.Find("div")。
func main() { html := `DIV1DIV2SPAN ` dom,err:=goquery.NewDocumentFromReader(strings.NewReader(html)) if err!=nil{ log.Fatalln(err) } dom.Find("div").Each(func(i int, selection *goquery.Selection) { fmt.Println(selection.Text()) }) } 以上示例,可以把div元素筛选出来,而body,span并不会被筛选。
ID 选择器
这个是使用频次最多的,类似于上面的例子,有两个div元素,其实我们只需要其中的一个,那么我们只需要给这个标记一个唯一的id即可,这样我们就可以使用id选择器,精确定位了。
func main() { html := `DIV1DIV2SPAN ` dom,err:=goquery.NewDocumentFromReader(strings.NewReader(html)) if err!=nil{ log.Fatalln(err) } dom.Find("#div1").Each(func(i int, selection *goquery.Selection) { fmt.Println(selection.Text()) }) } Element ID 选择器
id选择器以#开头,紧跟着元素id的值,使用语法为dom.Find(#id),后面的例子我会简写为Find(#id),大家知道这是代表goquery选择器的即可。
如果有相同的ID,但是它们又分别属于不同的HTML元素怎么办?有好办法,和Element结合起来。比如我们筛选元素为div,并且id是div1的元素,就可以使用Find(div#div1)这样的筛选器进行筛选。
所以这类筛选器的语法为Find(element#id),这是常用的组合方法,比如后面讲的过滤器也可以采用这种方式组合使用。
Class选择器
class也是HTML中常用的属性,我们可以通过class选择器来快速的筛选需要的HTML元素,它的用法和ID选择器类似,为Find(".class")。
func main() { html := `DIV1DIV2SPAN ` dom,err:=goquery.NewDocumentFromReader(strings.NewReader(html)) if err!=nil{ log.Fatalln(err) } dom.Find(".name").Each(func(i int, selection *goquery.Selection) { fmt.Println(selection.Text()) }) } 以上示例中,就筛选出来class为name的这个div元素。
Element Class 选择器
class选择器和id选择器一样,也可以结合着HTML元素使用,他们的语法也类似Find(element.class),这样就可以筛选特定element、并且指定class的元素。
属性选择器
一个HTML元素都有自己的属性以及属性值,所以我们也可以通过属性和值筛选元素。
func main() { html := `DIV1DIV2SPAN ` dom,err:=goquery.NewDocumentFromReader(strings.NewReader(html)) if err!=nil{ log.Fatalln(err) } dom.Find("div[class]").Each(func(i int, selection *goquery.Selection) { fmt.Println(selection.Text()) }) } 示例中我们通过div[class]这个选择器,筛选出Element为div并且有class这个属性的,所以第一个div没有被筛选到。
刚刚上面这个示例是采用是否存在某个属性为筛选器,同理,我们可以筛选出属性为某个值的元素。
dom.Find("div[class=name]").Each(func(i int, selection *goquery.Selection) { fmt.Println(selection.Text()) }) 这样我们就可以筛选出class这个属性值为name的div元素。
当然我们这里以class属性为例,还可以用其他属性,比如href等很多,自定义属性也是可以的。
除了完全相等,还有其他匹配方式,使用方式类似,这里统一列举下,不再举例
| 选择器 | 说明 |
|---|---|
| Find(“div[lang]”) | 筛选含有lang属性的div元素 |
| Find(“div[lang=zh]”) | 筛选lang属性为zh的div元素 |
| Find(“div[lang!=zh]”) | 筛选lang属性不等于zh的div元素 |
| Find(“div[lang¦=zh]”) | 筛选lang属性为zh或者zh-开头的div元素 |
| Find(“div[lang*=zh]”) | 筛选lang属性包含zh这个字符串的div元素 |
| Find(“div[lang~=zh]”) | 筛选lang属性包含zh这个单词的div元素,单词以空格分开的 |
| Find(“div[lang$=zh]”) | 筛选lang属性以zh结尾的div元素,区分大小写 |
| Find(“div[lang^=zh]”) | 筛选lang属性以zh开头的div元素,区分大小写 |
以上是属性筛选器的用法,都是以一个属性筛选器为例,当然你也可以使用多个属性筛选器组合使用,比如: Find("div[id][lang=zh]"),用多个中括号连起来即可。当有多个属性筛选器的时候,要同时满足这些筛选器的元素才能被筛选出来。
parent>child选择器
如果我们想筛选出某个元素下符合条件的子元素,我们就可以使用子元素筛选器,它的语法为Find("parent>child"),表示筛选parent这个父元素下,符合child这个条件的最直接(一级)的子元素。
func main() { html := `DIV1DIV2DIV3DIV4 ` dom,err:=goquery.NewDocumentFromReader(strings.NewReader(html)) if err!=nil{ log.Fatalln(err) } dom.Find("body>div").Each(func(i int, selection *goquery.Selection) { fmt.Println(selection.Text()) }) } 以上示例,筛选出body这个父元素下,符合条件的最直接的子元素div,结果是DIV1、DIV2、DIV3,虽然DIV4也是body的子元素,但不是一级的,所以不会被筛选到。
那么问题来了,我就是想把DIV4也筛选出来怎么办?就是要筛选body下所有的div元素,不管是一级、二级还是N级。有办法的,goquery考虑到了,只需要把大于号(>)改为空格就好了。比如上面的例子,改为如下选择器即可。
dom.Find("body div").Each(func(i int, selection *goquery.Selection) { fmt.Println(selection.Text()) }) prev+next相邻选择器
假设我们要筛选的元素没有规律,但是该元素的上一个元素有规律,我们就可以使用这种下一个相邻选择器来进行选择。
func main() { html := `DIV1P1
DIV2DIV3DIV4P2
` dom,err:=goquery.NewDocumentFromReader(strings.NewReader(html)) if err!=nil{ log.Fatalln(err) } dom.Find("div[lang=zh]+p").Each(func(i int, selection *goquery.Selection) { fmt.Println(selection.Text()) }) } 这个示例演示了这种用法,我们想选择 P1这个元素,但是没啥规律,我们发现它前面的很有规律,可以选择,所以我们就可以采用Find("div[lang=zh]+p")达到选择P元素的目的。
这种选择器的语法是("prev+next"),中间是一个加号(+),+号前后也是选择器。
prev~next选择器
有相邻就有兄弟,兄弟选择器就不一定要求相邻了,只要他们共有一个父元素就可以。
dom.Find("div[lang=zh]~p").Each(func(i int, selection *goquery.Selection) { fmt.Println(selection.Text()) }) 刚刚的例子,只需要把+号换成~号,就可以把P2也筛选出来,因为P2、P1和DIV1都是兄弟。
兄弟选择器的语法是("prev~next"),也就是相邻选择器的+换成了~。
内容过滤器
有时候我们使用选择器选择出来后后,希望再过滤一下,这时候就用到过滤器了,过滤器有很多,我们先讲内容过滤器这一种。
dom.Find("div:contains(DIV2)").Each(func(i int, selection *goquery.Selection) { fmt.Println(selection.Text()) }) Find(":contains(text)")表示筛选出的元素要包含指定的文本,我们例子中要求选择出的div元素要包含DIV2文本,那么只有一个DIV2元素满足要求。
此外还有Find(":empty")表示筛选出的元素都不能有子元素(包括文本元素),只筛选那些不包含任何子元素的元素。
Find(":has(selector)")和contains差不多,只不过这个是包含的是元素节点。
dom.Find("span:has(div)").Each(func(i int, selection *goquery.Selection) { fmt.Println(selection.Text()) }) 以上示例表示筛选出包含div元素的span节点。
:first-child过滤器
:first-child过滤器,语法为Find(":first-child"),表示筛选出的元素要是他们的父元素的第一个子元素,如果不是,则不会被筛选出来。
func main() { html := `DIV1P1
DIV2DIV3DIV5P2
` dom,err:=goquery.NewDocumentFromReader(strings.NewReader(html)) if err!=nil{ log.Fatalln(err) } dom.Find("div:first-child").Each(func(i int, selection *goquery.Selection) { fmt.Println(selection.Html()) }) } 以上例子中,我们使用Find("div")会筛选出所有的div元素,但是我们加了:first-child后,就只有DIV1和DIV4了,因为只有这两个是他们父元素的第一个子元素,其他的DIV都不满足。
:first-of-type过滤器
:first-child选择器限制的比较死,必须得是第一个子元素,如果该元素前有其他在前面,就不能用:first-child了,这时候:first-of-type就派上用场了,它要求只要是这个类型的第一个就可以,我们把上面的例子微调下。
func main() { html := `DIV1P1
DIV2DIV3<
相关内容
- Go time包AddDate使用解惑实例详解_Golang_
- windows下使用vscode搭建golang环境并调试的过程_Golang_
- mayfly-go部署和使用详解_Golang_
- golang 常用定时任务汇总_Golang_
- Go语言如何使用golang-jwt/jwt/v4进行JWT鉴权详解_Golang_
- golang包循环引用的几种解决方案总结_Golang_
- Go语言实现运算符重载的方法详解_Golang_
- GO 语言运行环境的基础知识_Golang_
- 一文带你了解Go语言中的类型断言和类型转换_Golang_
- Golang中字符串(string)与字节数组([]byte)一行代码互转实例_Golang_
点击排行
本栏推荐
