
在 goquery 中,html 元素的 `class="text title"` 表示该元素同时拥有两个独立的 class 名(`text` 和 `title`),需用 `.text.title` 连写形式匹配,而非空格分隔;单类名则直接用 `.title` 即可。
HTML 规范规定,class 属性值是一个以空格分隔的类名列表,每个单词代表一个独立的 CSS 类。因此 并非拥有一个名为 "text title" 的单一类,而是同时具有 text 和 title 两个类。goquery 遵循标准 CSS 选择器语法,. 前缀表示 class 选择器,多个类名需连续书写、无空格、各加一个点号,即 .text.title —— 这等价于 CSS 中的 .text.title,语义为“同时包含 text 和 title 两个类的元素”。
以下为完整可运行示例:
package main
import (
"fmt"
"github.com/PuerkitoBio/goquery"
"strings"
)
func main() {
htmlCode := strings.NewReader(`
Go
totally
kicks
hacks
`)
doc, err := goquery.NewDocumentFromReader(htmlCode)
if err != nil {
panic(err)
}
// ✅ 正确:查找同时具有 "text" 和 "title" 两个类的元素
fmt.Println("=== .text.title ===")
doc.Find(".text.title").Each(func(i int, s *goquery.Selection) {
class, _ := s.Attr("class")
fmt.Printf("class=%q, text=%q\n", class, s.Text())
})
// ✅ 正确:仅查找含 "title" 类的元素(无论是否还有其他类)
fmt.Println("\n=== .title ===")
doc.Find(".title").Each(func(i int, s *goquery.Selection) {
class, _ := s.Attr("class")
fmt.Printf("class=%q, text=%q\n", class, s.Text())
})
// ❌ 错误:".text title" 是后代选择器,会匹配 在 .text 元素内部的结构
// (本例中无此类嵌套,故不输出)
fmt.Println("\n=== .text title (incorrect) ===")
doc.Find(".text title").Each(func(i int, s *goquery.Selection) {
class, _ := s.Attr("class")
fmt.Printf("class=%q, text=%q\n", class, s.Text())
})
}输出结果:
=== .text.title === class="text title", text="Go " === .title === class="text title", text="Go " === .text title (incorrect) ===
⚠️ 注意事项:
立即学习“前端免费学习笔记(深入)”;
- .text.title 是交集选择器(AND 关系),要求元素同时具备所有指定类;
- .text 或 .title 是单类选择器,只要包含对应类即命中;
- .text title(带空格)是后代选择器(descendant combinator),意为“在 .text 元素内部的 title 元素”,与 class 匹配无关;
- 若需模糊匹配(如 class 值包含某子串),goquery 不原生支持,需结合 Filter() 方法配合正则或字符串操作,例如:
doc.Find("*").Filter(func(i int, s *goquery.Selection) bool { class, exists := s.Attr("class") return exists && strings.Contains(class, "text title") })
掌握 class 的多值本质与 CSS 选择器语义,是高效使用 goquery 解析 HTML 的关键基础。











