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 是一个非常高效且成熟的解决方案。

相关推荐
golang学习记2 小时前
从“大泥球“到模块化单体:Spring Modulith + IntelliJ IDEA 拯救你的代码
后端·intellij idea
颜酱2 小时前
一步步实现字符串计算器:从「转整数」到「带括号与优化」
javascript·后端·算法
离开地球表面_992 小时前
金三银四程序员跳槽指南:从简历到面试再到 Offer 的全流程准备
前端·后端·面试
UrbanJazzerati2 小时前
Scrapling入门指南:零基础也能学会的网页抓取神器
后端·面试
张洪权2 小时前
mysql + nest.js 加锁 搞并发问题
后端
郡杰2 小时前
MyBatisPlus
后端
beata2 小时前
Java基础-18:Java开发中的常用设计模式:深入解析与实战应用
java·后端
Qlly2 小时前
DDD 架构为什么适合 MCP Server 开发?
人工智能·后端·架构
苏三说技术3 小时前
Prompt、Agent、Function Call、Skill、MCP,傻傻分不清楚?
后端