golang实现类似jQuery的HTML解析与操作插件库GoQuery的使用
Golang实现类似jQuery的HTML解析与操作插件库GoQuery的使用
GoQuery简介
GoQuery是一个为Go语言提供的库,它带来了类似jQuery的语法和功能集。GoQuery基于Go的net/html包和CSS选择器库cascadia构建。
由于net/html解析器返回的是节点而不是完整的DOM树,因此jQuery的有状态操作函数(如height()、css()、detach())没有被包含在内。
安装
Go版本要求:
- 从v1.10.0版本开始,GoQuery需要Go 1.23+,因为使用了基于函数的迭代器
- 对于v1.9.0版本,需要Go 1.18+,因为使用了泛型
- 对于更早的GoQuery版本,由于net/html依赖关系,需要Go 1.1+
安装命令:
$ go get github.com/PuerkitoBio/goquery
(可选)运行单元测试:
$ cd $GOPATH/src/github.com/PuerkitoBio/goquery
$ go test
基本用法示例
下面是一个完整的GoQuery使用示例,展示了如何从网页中抓取并解析数据:
package main
import (
"fmt"
"log"
"net/http"
"github.com/PuerkitoBio/goquery"
)
func ExampleScrape() {
// 请求HTML页面
res, err := http.Get("http://metalsucks.net")
if err != nil {
log.Fatal(err)
}
defer res.Body.Close()
if res.StatusCode != 200 {
log.Fatalf("status code error: %d %s", res.StatusCode, res.Status)
}
// 加载HTML文档
doc, err := goquery.NewDocumentFromReader(res.Body)
if err != nil {
log.Fatal(err)
}
// 查找评论项
doc.Find(".left-content article .post-title").Each(func(i int, s *goquery.Selection) {
// 对于每个找到的项目,获取标题
title := s.Find("a").Text()
fmt.Printf("Review %d: %s\n", i, title)
})
}
func main() {
ExampleScrape()
}
API设计
GoQuery暴露了两个结构体Document
和Selection
,以及Matcher
接口。与jQuery不同,GoQuery需要被告知要操作哪个HTML文档,这就是Document
类型的作用。它保存根文档节点作为初始的Selection值来操作。
GoQuery遵循以下命名约定:
- 当jQuery等效函数可以不带参数调用时,它与jQuery同名(如
Prev()
),带有选择器字符串参数的版本称为XxxFiltered()
(如PrevFiltered()
) - 当jQuery等效函数需要一个参数时,使用与jQuery相同的名称作为选择器字符串版本(如
Is()
) - 接受jQuery对象作为参数的签名在goquery中定义为
XxxSelection()
并接受*Selection
对象作为参数(如FilterSelection()
) - 在jQuery中接受DOM元素作为参数的签名在goquery中定义为
XxxNodes()
并接受类型为*html.Node
的可变参数(如FilterNodes()
) - 在jQuery中接受函数作为参数的签名在goquery中定义为
XxxFunction()
并接受函数作为参数(如FilterFunction()
)
注意事项
- Cascadia的选择器不一定匹配jQuery(Sizzle)支持的所有选择器
- 选择器的工作方式更像DOM的
querySelectorAll
,而不是jQuery的匹配器 - 无效的选择器字符串编译为不匹配任何节点的
Matcher
相关项目
- Goq:基于goquery和结构标签的HTML反序列化和抓取库
- andybalholm/cascadia:GoQuery使用的CSS选择器库
- gocolly/colly:一个快速优雅的抓取框架
- MontFerret/ferret:声明式网页抓取
- Dataflow kit:面向Gopher的网页抓取框架
- Geziyor:Go的快速网页爬取和抓取框架,支持JS渲染
支持项目
有多种方式可以支持这个项目:
- 使用它、加星标、用它构建东西、传播它!
- 提出改进项目的问题
- 提交Pull请求
- 赞助开发者
许可证
BSD 3-Clause许可证,与Go语言相同。Cascadia的许可证在这里。
更多关于golang实现类似jQuery的HTML解析与操作插件库GoQuery的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于golang实现类似jQuery的HTML解析与操作插件库GoQuery的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
GoQuery: Golang中的jQuery风格HTML解析库
GoQuery是一个流行的Golang库,它实现了类似jQuery的语法和功能,用于解析和操作HTML文档。下面我将详细介绍GoQuery的使用方法。
安装GoQuery
首先需要安装GoQuery及其依赖:
go get github.com/PuerkitoBio/goquery
基本用法
1. 从字符串创建文档
package main
import (
"fmt"
"github.com/PuerkitoBio/goquery"
"log"
"strings"
)
func main() {
html := `<html>
<head>
<title>示例页面</title>
</head>
<body>
<div id="content">
<h1>标题</h1>
<p class="intro">介绍段落</p>
<ul>
<li>项目1</li>
<li>项目2</li>
<li>项目3</li>
</ul>
</div>
</body>
</html>`
// 从字符串创建文档
doc, err := goquery.NewDocumentFromReader(strings.NewReader(html))
if err != nil {
log.Fatal(err)
}
// 查找标题
title := doc.Find("title").Text()
fmt.Println("标题:", title)
}
2. 从URL加载文档
func main() {
// 从URL加载文档
doc, err := goquery.NewDocument("http://example.com")
if err != nil {
log.Fatal(err)
}
// 查找所有链接
doc.Find("a").Each(func(i int, s *goquery.Selection) {
href, exists := s.Attr("href")
if exists {
fmt.Printf("链接 %d: %s\n", i+1, href)
}
})
}
常用选择器
GoQuery支持大部分jQuery选择器:
// ID选择器
doc.Find("#content")
// 类选择器
doc.Find(".intro")
// 元素选择器
doc.Find("h1")
// 属性选择器
doc.Find("input[name='email']")
// 后代选择器
doc.Find("div p") // div下的所有p元素
// 子元素选择器
doc.Find("ul > li") // ul的直接子元素li
// 相邻兄弟选择器
doc.Find("h1 + p") // 紧接在h1后的p元素
// 通用兄弟选择器
doc.Find("h1 ~ p") // h1之后的所有p兄弟元素
遍历和操作
1. 遍历元素
doc.Find("li").Each(func(i int, s *goquery.Selection) {
fmt.Printf("项目 %d: %s\n", i+1, s.Text())
})
2. 获取和设置属性
// 获取属性
href, exists := doc.Find("a").Attr("href")
// 设置属性
doc.Find("img").SetAttr("alt", "描述文字")
3. 获取和修改内容
// 获取文本内容
text := doc.Find("p").Text()
// 获取HTML内容
html, _ := doc.Find("div").Html()
// 设置文本内容
doc.Find("h1").SetText("新标题")
// 设置HTML内容
doc.Find("div").SetHtml("<p>新内容</p>")
4. 添加和删除元素
// 追加元素
doc.Find("ul").Append("<li>新项目</li>")
// 前置元素
doc.Find("ul").Prepend("<li>第一个项目</li>")
// 删除元素
doc.Find(".ad").Remove()
// 保留元素但删除其内容
doc.Find("div").Empty()
过滤和查找
1. 过滤元素
// 按位置过滤
firstItem := doc.Find("li").First()
lastItem := doc.Find("li").Last()
thirdItem := doc.Find("li").Eq(2) // 索引从0开始
// 按条件过滤
evenItems := doc.Find("li").Even() // 偶数位置
oddItems := doc.Find("li").Odd() // 奇数位置
filtered := doc.Find("li").Filter(".active") // 带active类的li
2. 查找子元素
// 查找子元素
children := doc.Find("ul").Children()
// 查找后代元素
descendants := doc.Find("div").Find("p")
3. 查找父元素和祖先元素
// 直接父元素
parent := doc.Find("li").Parent()
// 所有祖先元素
parents := doc.Find("li").Parents()
// 最近的匹配祖先
closestDiv := doc.Find("span").Closest("div")
实际应用示例
1. 抓取网页内容
func scrapeExample() {
doc, err := goquery.NewDocument("https://example.com")
if err != nil {
log.Fatal(err)
}
// 提取所有段落文本
doc.Find("p").Each(func(i int, s *goquery.Selection) {
fmt.Printf("段落 %d: %s\n", i+1, s.Text())
})
// 提取特定数据
title := doc.Find("h1").Text()
description, _ := doc.Find("meta[name='description']").Attr("content")
fmt.Printf("标题: %s\n描述: %s\n", title, description)
}
2. 修改HTML文档
func modifyHTML() {
html := `<div class="container"><p>原始内容</p></div>`
doc, _ := goquery.NewDocumentFromReader(strings.NewReader(html))
// 修改内容
doc.Find(".container").SetHtml(`
<h1>新标题</h1>
<p>第一段</p>
<p>第二段</p>
`)
// 添加类
doc.Find("p").AddClass("text-paragraph")
// 移除类
doc.Find("h1").RemoveClass("old-class")
// 获取修改后的HTML
newHTML, _ := doc.Html()
fmt.Println(newHTML)
}
注意事项
- GoQuery不是浏览器,不执行JavaScript
- 对于大型HTML文档,注意内存使用
- 网络请求可能需要设置超时和用户代理
- 处理动态内容可能需要结合其他工具如chromedp
GoQuery提供了强大而熟悉的jQuery风格API,使得在Go中处理HTML变得简单直观。无论是网页抓取还是HTML处理,它都是一个非常实用的工具。