GoHTML解析利器:github.com/PuerkitoBio/goquery实战指南

在做网页爬虫、HTML 数据抓取、自动化数据采集时,Go 语言中最常用的 HTML 解析库之一就是:

github.com/PuerkitoBio/goquery

它提供了类似 JavaScript 中 jQuery 的 DOM 操作方式,使得 HTML 解析变得非常直观和高效。


一、goquery 是什么

goquery 是一个 Go 语言的 HTML 文档解析和 DOM 操作库,由 Martin Angers 开发维护。

该库的设计理念是:

在 Go 中实现类似 jQuery 的 DOM 选择和操作方式。

核心特点:

  • • 使用 CSS Selector 选择元素
  • • API 风格类似 jQuery
  • • 基于 Go 标准库 HTML 解析器
  • • 操作简单且性能稳定

goquery 的底层解析器来自 Go 官方 HTML 解析库:

golang.org/x/net/html


二、为什么使用 goquery

在 Go 中解析 HTML 有多种方式:

1 使用正则表达式

2 使用 golang.org/x/net/html

3 使用 goquery

其中 goquery 的优势非常明显。

使用正则解析 HTML:

  • • 代码复杂
  • • 容易出错
  • • 不适合复杂结构

使用 html 原生解析:

  • • API 偏底层
  • • 操作较繁琐

goquery 提供了更高级的 DOM 查询接口,使 HTML 解析更接近前端开发体验。


三、安装 goquery

在 Go 项目中安装:

arduino 复制代码
go get github.com/PuerkitoBio/goquery

导入库:

arduino 复制代码
import "github.com/PuerkitoBio/goquery"

四、解析 HTML 文档

最基础的使用方式是解析 HTML 字符串或网页。

示例:

go 复制代码
package main

import (
    "fmt"
    "strings"

    "github.com/PuerkitoBio/goquery"
)

func main() {

    html := `
    <html>
    <body>
    <div class="title">Hello GoQuery</div>
    </body>
    </html>
    `

    doc, err := goquery.NewDocumentFromReader(strings.NewReader(html))
    if err != nil {
        panic(err)
    }

    text := doc.Find(".title").Text()

    fmt.Println(text)
}

输出:

Hello GoQuery


五、从网页 URL 直接解析

goquery 提供了一个非常方便的函数,可以直接解析网页。

go 复制代码
package main

import (
    "fmt"

    "github.com/PuerkitoBio/goquery"
)

func main() {

    doc, err := goquery.NewDocument("https://example.com")
    if err != nil {
        panic(err)
    }

    fmt.Println(doc.Find("title").Text())
}

适用于:

  • • 简单爬虫
  • • 快速数据采集

不过在生产环境中通常建议使用自定义 HTTP 请求。


六、使用 CSS 选择器

goquery 支持常见的 CSS Selector。

例如:

选择 class

arduino 复制代码
doc.Find(".product")

选择 id

arduino 复制代码
doc.Find("#main")

选择标签

arduino 复制代码
doc.Find("a")

组合选择

css 复制代码
doc.Find("div.product a.title")

属性选择

css 复制代码
doc.Find("img[data-src]")

这些写法与 jQuery 几乎一致。


七、遍历元素

在抓取数据时,经常需要遍历列表元素。

示例:

css 复制代码
doc.Find(".item").Each(func(i int, s *goquery.Selection) {

    title := s.Find(".title").Text()

    link, _ := s.Find("a").Attr("href")

    fmt.Println(title, link)

})

Each 会遍历所有匹配的元素。


八、读取元素属性

例如读取图片地址:

css 复制代码
src, exists := doc.Find("img").Attr("src")

if exists {
    fmt.Println(src)
}

常见属性:

  • • href
  • • src
  • • data-*

九、修改 HTML 内容

goquery 不仅可以读取,还可以修改 DOM。

修改文本:

arduino 复制代码
doc.Find(".title").SetText("New Title")

添加属性:

arduino 复制代码
doc.Find("img").SetAttr("alt", "image")

删除元素:

scss 复制代码
doc.Find(".ad").Remove()

十、获取完整 HTML

如果修改了 HTML,可以重新输出。

css 复制代码
html, err := doc.Html()

也可以输出某个节点:

css 复制代码
html, err := doc.Find(".content").Html()

十一、完整爬虫示例

下面是一个简单的网页抓取示例。

go 复制代码
package main

import (
    "fmt"
    "net/http"

    "github.com/PuerkitoBio/goquery"
)

func main() {

    resp, err := http.Get("https://example.com")
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()

    doc, err := goquery.NewDocumentFromReader(resp.Body)
    if err != nil {
        panic(err)
    }

    doc.Find("a").Each(func(i int, s *goquery.Selection) {

        text := s.Text()

        link, _ := s.Attr("href")

        fmt.Println(text, link)

    })
}

这个程序会抓取页面中所有链接。


十二、性能建议

在大规模爬虫项目中,可以做以下优化:

1 使用 HTTP 连接池

2 并发抓取多个页面

3 减少不必要的 DOM 查询

4 提前筛选 HTML 结构

goquery 本身性能不错,但 HTML 解析仍然属于 CPU 密集操作。


十三、典型应用场景

goquery 非常适合以下场景:

网页爬虫

SEO 数据采集

电商商品抓取

新闻内容采集

HTML 数据提取

自动化测试

例如抓取:

  • • 商品标题
  • • 商品价格
  • • 图片链接
  • • 文章正文

十四、常见问题

HTML 解析失败

原因通常是 HTML 不完整,可以先打印 HTML 内容确认。

网页需要 JavaScript

goquery 只能解析静态 HTML。

如果网页依赖 JavaScript 渲染,需要使用浏览器自动化工具,例如:

Chromium

或无头浏览器方案。


十五、总结

github.com/PuerkitoBio/goquery 是 Go 生态中最流行的 HTML 解析库之一。

主要优势:

  • • jQuery 风格 API
  • • 支持 CSS Selector
  • • 使用简单
  • • 适合爬虫开发

对于需要抓取网页结构化数据的 Go 项目来说,goquery 是一个非常高效且成熟的解决方案。

相关推荐
ttwuai3 小时前
Cursor 生成 CRUD 后,Go 后台接口别只测 200:JWT、RBAC 和 tenant_id 怎么验
开发语言·后端·golang
用户8356290780513 小时前
Python 实现 Excel 页面布局与打印设置自动化
后端·python
用户9931441579843 小时前
微服务框架中获取用户信息
后端
xuanWb3 小时前
手写一个 LLM API 网关:Anthropic 与 OpenAI 协议转换的完整实现
后端
苍何3 小时前
给 Codex 换皮肤这门生意,被我开源了
后端
用户8356290780513 小时前
Python 实现 Excel 命名范围(Named Range)的创建与管理
后端·python
程序员David4 小时前
我让 Claude 从架构文档一路干到代码,踩了三个坑才摸清边界
后端
Zane19944 小时前
并发 vs 并行:别再傻傻分不清了,一文讲透 Java 并发编程的第一课
java·后端
码哥字节4 小时前
Google 上周推了个 agents-cli,我装完发现 Claude Code 多了 7 个超能力
google·agent·claude
神奇小汤圆4 小时前
线程池拒绝策略CallerRunsPolicy反而卡死了主线程
后端