golang使用jQuery语法进行HTML声明式解析插件库goq的使用
Golang使用jQuery语法进行HTML声明式解析插件库goq的使用
goq是一个Golang库,允许用户使用类似jQuery的CSS选择器语法来声明式地将HTML解组到Go结构体中。
示例
下面是一个完整的示例,展示如何使用goq从GitHub页面提取标题和文件列表:
import (
"log"
"net/http"
"astuart.co/goq"
)
// 定义结构体来表示GitHub文件名称表格
type example struct {
Title string `goquery:"h1"` // 提取h1标签的文本
Files []string `goquery:"table.files tbody tr.js-navigation-item td.content,text"` // 提取表格中的文件列表
}
func main() {
// 获取GitHub页面
res, err := http.Get("https://github.com/andrewstuart/goq")
if err != nil {
log.Fatal(err)
}
defer res.Body.Close()
var ex example
// 使用goq解析HTML到结构体
err = goq.NewDecoder(res.Body).Decode(&ex)
if err != nil {
log.Fatal(err)
}
// 输出提取的结果
log.Println(ex.Title, ex.Files)
}
使用说明
goq包的设计目的是让用户能够使用由CSS选择器组成的结构标签,声明式地将HTML解组到Go结构体中。
创建要解组到的结构体类型时,适用以下一般规则:
-
任何实现Unmarshaler接口的类型都将传递一个
*html.Node
切片,以便可以手动解组。这具有最高优先级。 -
任何结构字段都可以用goquery元数据注释,其形式为元素选择器后跟任意逗号分隔的"值选择器"。
-
值选择器可以是
html
、text
或[someAttrName]
之一:html
和text
将导致在*goquery.Selection
上调用同名方法以获取值[someAttrName]
将导致调用*goquery.Selection.Attr("someAttrName")
来获取值
-
如果没有给出值选择器,原始值类型将默认为结果节点的文本值。
-
对于映射,至少需要一个值选择器来确定映射键。键类型必须遵循适用于Go映射索引的规则以及这些解组规则。每个键的值将以与元素值相同的方式解组。
核心功能
解码HTML
func Unmarshal(bs []byte, v interface{}) error
Unmarshal接受一个字节切片和一个目标接口指针,并根据上述规则将文档解组到目标中。
解码选择器
func UnmarshalSelection(s *goquery.Selection, iface interface{}) error
UnmarshalSelection将goquery.Selection解组到适当注释的接口中。
自定义解码器
type Decoder struct {}
func NewDecoder(r io.Reader) *Decoder
func (d *Decoder) Decode(dest interface{}) error
Decoder实现了与encoding/xml和encoding/json相同的API,只是目前不支持适当的流解码,因为上游goquery不支持。
自定义解组
type Unmarshaler interface {
UnmarshalHTML([]*html.Node) error
}
Unmarshaler允许自定义解组逻辑的实现。
错误处理
type CannotUnmarshalError struct {
Err error
Val string
FldOrIdx interface{}
}
CannotUnmarshalError表示由goquery Unmarshaler返回的错误,并帮助用户以编程方式诊断其错误原因。
实用函数
func NodeSelector(nodes []*html.Node) *goquery.Selection
NodeSelector是一个快速实用函数,用于从*html.Node
切片获取goquery.Selection。
更多关于golang使用jQuery语法进行HTML声明式解析插件库goq的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于golang使用jQuery语法进行HTML声明式解析插件库goq的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
Goq: Go语言中的jQuery风格HTML解析库
Goq是一个Go语言的HTML解析库,它提供了类似jQuery的选择器语法,使得在Go中解析HTML文档变得更加简单直观。下面我将详细介绍goq的使用方法。
安装
首先安装goq库:
go get github.com/andrewstuart/goq
基本用法
1. 解析HTML文档
package main
import (
"fmt"
"github.com/andrewstuart/goq"
"strings"
)
func main() {
html := `
<html>
<body>
<div class="content">
<h1>标题</h1>
<p>段落1</p>
<p>段落2</p>
<ul>
<li>项目1</li>
<li>项目2</li>
</ul>
</div>
</body>
</html>
`
// 解析HTML
doc, err := goq.NewDoc(strings.NewReader(html))
if err != nil {
panic(err)
}
// 使用选择器
title := doc.Find("h1").Text()
fmt.Println("标题:", title) // 输出: 标题: 标题
// 获取所有段落
paragraphs := doc.Find("p")
fmt.Println("段落数量:", paragraphs.Length()) // 输出: 段落数量: 2
// 遍历元素
paragraphs.Each(func(i int, sel *goq.Selection) {
fmt.Printf("段落%d: %s\n", i+1, sel.Text())
})
// 输出:
// 段落1: 段落1
// 段落2: 段落2
}
2. 类似jQuery的选择器语法
// 类选择器
doc.Find(".content").Each(func(i int, sel *goq.Selection) {
fmt.Println("找到class为content的元素:", sel.Text())
})
// ID选择器
doc.Find("#main").Each(func(i int, sel *goq.Selection) {
fmt.Println("找到id为main的元素:", sel.Text())
})
// 属性选择器
doc.Find("a[href]").Each(func(i int, sel *goq.Selection) {
href, _ := sel.Attr("href")
fmt.Println("链接:", href)
})
// 后代选择器
doc.Find("div p").Each(func(i int, sel *goq.Selection) {
fmt.Println("div下的p元素:", sel.Text())
})
3. 获取和修改属性
// 获取属性
doc.Find("a").Each(func(i int, sel *goq.Selection) {
href, exists := sel.Attr("href")
if exists {
fmt.Println("链接地址:", href)
}
})
// 设置属性
doc.Find("img").SetAttr("alt", "图片描述")
4. 链式调用
text := doc.Find("div.content").
Find("p").
First().
Text()
fmt.Println("第一个段落:", text)
5. 过滤和查找
// 过滤
doc.Find("li").Filter(func(i int, sel *goq.Selection) bool {
return strings.Contains(sel.Text(), "2")
}).Each(func(i int, sel *goq.Selection) {
fmt.Println("包含'2'的li:", sel.Text())
})
// 查找子元素
doc.Find("ul").Children().Each(func(i int, sel *goq.Selection) {
fmt.Println("ul的子元素:", sel.Text())
})
实际应用示例:解析网页内容
package main
import (
"fmt"
"github.com/andrewstuart/goq"
"net/http"
)
func main() {
// 获取网页内容
resp, err := http.Get("https://example.com")
if err != nil {
panic(err)
}
defer resp.Body.Close()
// 解析HTML
doc, err := goq.NewDoc(resp.Body)
if err != nil {
panic(err)
}
// 提取所有链接
doc.Find("a").Each(func(i int, sel *goq.Selection) {
href, _ := sel.Attr("href")
text := sel.Text()
fmt.Printf("链接%d: %s (%s)\n", i+1, text, href)
})
// 提取页面标题
title := doc.Find("title").Text()
fmt.Println("页面标题:", title)
}
注意事项
- goq不是真正的jQuery,它只实现了jQuery的部分选择器功能
- 对于大型HTML文档,性能可能不如标准库的html包
- 如果只需要简单解析,标准库的
golang.org/x/net/html
可能更高效
总结
goq为Go语言开发者提供了类似jQuery的HTML解析体验,使得从HTML文档中提取数据变得更加简单直观。它的链式调用和选择器语法让代码更易读易写,特别适合需要快速从HTML中提取数据的场景。
虽然它不如原生解析器高效,但在大多数常见用例中,这种简洁的API带来的开发效率提升往往比微小的性能差异更有价值。