go爬虫框架 goquery 选择器


//参考博客 https://www.flysnow.org/2018/01/20/golang-goquery-examples-selector.html#%E9%80%89%E6%8B%A9%E5%99%A8%E6%88%96%E8%BF%90%E7%AE%97


package main

import (
	"fmt"
	"github.com/PuerkitoBio/goquery"
	"log"
	"strings"
)

func HtmlElement() {
html := `<body>
				<div>DIV1</div>
				<div>DIV2</div>
				<div id="aabb">DIV3</div>
				<p id="aabb">DIV4</p>
				<div class="name">DIV5</div>
				<div lang="aabb" class="name">DIV6</div>
				<span>
					<div>DIV7</div>
				</span>
				<p>PDIV</p>
				<p></p>
				<p>PDIV1</p>
			</body>
			`

	dom,err:=goquery.NewDocumentFromReader(strings.NewReader(html))
		if err!=nil{
	log.Fatalln(err)
	}

	//基于HTML Element 元素的选择器
	//匹配标签为div的元素,Each() 是迭代器,它会循环遍历选择的节点
	dom.Find("div").Each(func(i int, selection *goquery.Selection) {
		//Text() 则是获取匹配元素集中的文本内容
		fmt.Println(selection.Text())
	})

	//ID 选择器
	//选取 id="aabb" 的元素
	dom.Find("#aabb").Each(func(i int, selection *goquery.Selection) {
		fmt.Println(selection.Text())
	})

	//Element ID 选择器
	//有相同的ID,但是它们又分别属于不同的HTML元素
	//选取 <p id="aabb">DIV4</p>
	dom.Find("p#aabb").Each(func(i int, selection *goquery.Selection) {
		fmt.Println(selection.Text())
	})

	//Class选择器
	//选取 <div class="name">DIV5</div>
	dom.Find(".name").Each(func(i int, selection *goquery.Selection) {
		fmt.Println(selection.Text())
	})

	//Element Class 选择器
	//筛选出Element为div并且有class这个属性元素
	dom.Find("div[class]").Each(func(i int, selection *goquery.Selection) {
		fmt.Println(selection.Text())
	})
	//筛选出属性为某个值的元素
	dom.Find("div[class=name]").Each(func(i int, selection *goquery.Selection) {
		fmt.Println(selection.Text())
	})
	//多个属性筛选器组合使用
	dom.Find("div[lang=aabb][class=name]").Each(func(i int, selection *goquery.Selection) {
		fmt.Println(selection.Text())
	})
	/*其他匹配方式示例
	选择器	说明
	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元素,区分大小写
	*/

	//parent>child选择器
	//筛选出某个元素下符合条件的子元素
	//筛选parent这个父元素下,符合child这个条件的最直接(一级)的子元素
	//语法 Find("parent>child")
	//不会筛选 	<span> <div>DIV7</div> </span>,不是一级子元素
	dom.Find("body>div").Each(func(i int, selection *goquery.Selection) {
		fmt.Println(selection.Text())
	})
	//筛选出某个元素下所有的子元素
	//将 Find("parent>child") 中 > 改为空格
	dom.Find("body div").Each(func(i int, selection *goquery.Selection) {
		fmt.Println(selection.Text())
	})

	//prev+next相邻选择器
	//筛选的元素没有规律,上一个元素有规律
	//使用下一个相邻选择器来进行选择
	//选取 <p>PDIV</p>
	dom.Find("span+p").Each(func(i int, selection *goquery.Selection) {
		fmt.Println(selection.Text())
	})
	//选取 <p id="aabb">DIV4</p>
	dom.Find("div[id=aabb]+p").Each(func(i int, selection *goquery.Selection) {
		fmt.Println(selection.Text())
	})

	//prev~next选择器
	//不一定要求相邻了,共有一个父元素
	//选择共同父元素 p,选取 <p>PDIV</p>
	dom.Find("p[id=aabb]~p").Each(func(i int, selection *goquery.Selection) {
		fmt.Println("p[id=aabb]~p")
		fmt.Println(selection.Text())
	})

	//内容过滤器
	//语法 Find(":contains(text)") 筛选出的元素要包含指定的文本
	dom.Find("div:contains(DIV2)").Each(func(i int, selection *goquery.Selection) {
		fmt.Println(selection.Text())
	})
	//语法 Find(":empty") 筛选出的元素都不能有子元素(包括文本元素)
	//筛选出来的为空
	dom.Find("p:empty").Each(func(i int, selection *goquery.Selection) {
		fmt.Println("筛选出的元素都不能有子元素")
		fmt.Println(selection.Text())
	})
	//Find(":has(selector)")和contains差不多,只不过这个是包含的是元素节点。
	dom.Find("span:has(div)").Each(func(i int, selection *goquery.Selection) {
		fmt.Println(selection.Text())
	})

	//:first-child过滤器
	//语法 Find(":first-child")
	//筛选出的元素要是他们的父元素的第一个子元素,如果不是,则不会被筛选出来。
	//筛选 DIV1 DIV4,均为父元素的第一个元素
	dom.Find("div:first-child").Each(func(i int, selection *goquery.Selection) {
		fmt.Println(selection.Html())
	})

	//:first-of-type过滤器
	//该类型的第一个元素,限制比 :first-child 宽松
	//若 :first-child 筛选元素前面加一个元素,则筛选不出,使用 :first-of-type 则可以
	//比如将 <span> <div>DIV7</div> </span> 改成 <span> <p>DIVDIV</p> <div>DIV7</div> </span>
	// :first-child 筛选不出 DIV7 ,:first-of-type 则可以筛选出
	dom.Find("div:first-of-type").Each(func(i int, selection *goquery.Selection) {
		fmt.Println(selection.Html())
	})

	//:last-child 和 :last-of-type过滤器
	//表示与 first-child、:first-of-type相反,表示最后一个
	dom.Find("div:last-child").Each(func(i int, selection *goquery.Selection) {
		fmt.Println(selection.Html())
	})
	dom.Find("div:last-of-type").Each(func(i int, selection *goquery.Selection) {
		fmt.Println(selection.Html())
	})

	//:nth-child(n) 过滤器
	//筛选出的元素是其父元素的第n个元素,n以1开始
	//筛选出 DIV2
	dom.Find("div:nth-child(2)").Each(func(i int, selection *goquery.Selection) {
		fmt.Println(selection.Html())
	})

	//:nth-of-type(n) 过滤器
	//:nth-of-type(n)和 :nth-child(n) 类似,只不过它表示的是同类型元素的第n个,
	//所以:nth-of-type(1) 和 :first-of-type是相等的
	dom.Find("div:nth-of-type(2)").Each(func(i int, selection *goquery.Selection) {
		fmt.Println(selection.Html())
	})

	//nth-last-child(n) 和:nth-last-of-type(n) 过滤器
	//倒序开始计算的,最后一个元素被当成了第一个
	dom.Find("p:nth-last-child(1)").Each(func(i int, selection *goquery.Selection) {
		fmt.Println("p:nth-last-child(1)")
		fmt.Println(selection.Html())
	})
	dom.Find("div:nth-last-of-type(2)").Each(func(i int, selection *goquery.Selection) {
		fmt.Println("div:nth-last-of-type(2)")
		fmt.Println(selection.Html())
	})

	//:only-child 过滤器
	//语法 Find(":only-child")
	//父元素除了被筛选出来的元素,没有其他的子元素
	dom.Find("div:only-child").Each(func(i int, selection *goquery.Selection) {
		fmt.Println(selection.Html())
	})

	//:only-of-type 过滤器
	//同类型元素只要只有一个,就可以被筛选出来
	dom.Find("div:only-of-type").Each(func(i int, selection *goquery.Selection) {
		fmt.Println(selection.Html())
	})

	//选择器或(|)运算
	//多个选择器进行组合使用,并且以逗号(,)分割
	//只要满足其中一个选择器就可以被筛选出来,也就是选择器的或(|)运算操作。
	//语法 Find("selector1, selector2, selectorN")
	dom.Find("div,span").Each(func(i int, selection *goquery.Selection) {
		fmt.Println("div,span")
		fmt.Println(selection.Html())
	})

}

func main()  {
	HtmlElement()
}







猜你喜欢

转载自blog.csdn.net/liao__ran/article/details/120459541