goquery README

The project's README from github.com/PuerkitoBio/goquery. As one markdown file: README.md.

goquery - a little like that j-thing, only in Go

Build Status Go Reference Sourcegraph Badge

goquery brings a syntax and a set of features similar to jQuery to the Go language. It is based on Go's net/html package and the CSS Selector library cascadia. Since the net/html parser returns nodes, and not a full-featured DOM tree, jQuery's stateful manipulation functions (like height(), css(), detach()) have been left off.

Also, because the net/html parser requires UTF-8 encoding, so does goquery: it is the caller's responsibility to ensure that the source document provides UTF-8 encoded HTML. See the wiki for various options to do this.

Syntax-wise, it is as close as possible to jQuery, with the same function names when possible, and that warm and fuzzy chainable interface. jQuery being the ultra-popular library that it is, I felt that writing a similar HTML-manipulating library was better to follow its API than to start anew (in the same spirit as Go's fmt package), even though some of its methods are less than intuitive (looking at you, index()...).

Table of Contents

Installation

Required Go version:

Ongoing goquery development is tested on the latest 2 versions of Go.

$ go get github.com/PuerkitoBio/goquery

(optional) To run unit tests:

$ cd $GOPATH/src/github.com/PuerkitoBio/goquery
$ go test

(optional) To run benchmarks (warning: it runs for a few minutes):

$ cd $GOPATH/src/github.com/PuerkitoBio/goquery
$ go test -bench=".*"

Changelog

Note that goquery's API is now stable, and will not break.

API

goquery exposes two structs, Document and Selection, and the Matcher interface. Unlike jQuery, which is loaded as part of a DOM document, and thus acts on its containing document, goquery doesn't know which HTML document to act upon. So it needs to be told, and that's what the Document type is for. It holds the root document node as the initial Selection value to manipulate.

jQuery often has many variants for the same function (no argument, a selector string argument, a jQuery object argument, a DOM element argument, ...). Instead of exposing the same features in goquery as a single method with variadic empty interface arguments, statically-typed signatures are used following this naming convention:

Utility functions that are not in jQuery but are useful in Go are implemented as functions (that take a *Selection as parameter), to avoid a potential naming clash on the *Selection's methods (reserved for jQuery-equivalent behaviour).

The complete package reference documentation can be found here.

Please note that Cascadia's selectors do not necessarily match all supported selectors of jQuery (Sizzle). See the cascadia project for details. Also, the selectors work more like the DOM's querySelectorAll, than jQuery's matchers - they have no concept of contextual matching (for some concrete examples of what that means, see this ticket). In practice, it doesn't matter very often but it's something worth mentioning. Invalid selector strings compile to a Matcher that fails to match any node. Behaviour of the various functions that take a selector string as argument follows from that fact, e.g. (where ~ is an invalid selector string):

Examples

See some tips and tricks in the wiki.

Adapted from example_test.go:

package main

import (
  "fmt"
  "log"
  "net/http"

  "github.com/PuerkitoBio/goquery"
)

func ExampleScrape() {
  // Request the HTML page.
  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)
  }

  // Load the HTML document
  doc, err := goquery.NewDocumentFromReader(res.Body)
  if err != nil {
    log.Fatal(err)
  }

  // Find the review items
  doc.Find(".left-content article .post-title").Each(func(i int, s *goquery.Selection) {
		// For each item found, get the title
		title := s.Find("a").Text()
		fmt.Printf("Review %d: %s\n", i, title)
	})
}

func main() {
  ExampleScrape()
}

Support

There are a number of ways you can support the project:

Buy Me A Coffee

License

The BSD 3-Clause license, the same as the Go language. Cascadia's license is here.

goquery (PuerkitoBio/goquery)

Searching Database…

这是什么?goquery 是一个 Go 库,让你在解析和操作 HTML 时可以使用类似 jQuery 的语法和功能。它基于 Go 的 net/html 包和 cascadia 这个 CSS 选择器库构建。
如果我已经会用 jQuery,用起来会不会很眼熟?会非常眼熟:函数名和可链式调用的接口都尽量照搬 jQuery。区别在于 height()、css()、detach() 这类有状态的方法没有提供,因为 net/html 返回的是节点,而不是一个功能完整的 DOM 树。
怎么把它加到我的项目里?运行 'go get github.com/PuerkitoBio/goquery',导入这个包,把你的 HTML 包成一个 Document——比如用 NewDocumentFromReader——然后就可以用 Find() 开始选择元素了。
需要哪个 Go 版本?goquery v1.12.0 及更高版本要求 Go 1.25+;更早的版本系列分别要求 Go 1.24+、1.23+ 或 1.18+,而 v1.9 之前的版本最低支持到 Go 1.1。
随便扔给它什么 HTML 都能解析吗?只支持 UTF-8:底层的 net/html 解析器要求输入是 UTF-8 编码,所以确保源文档提供 UTF-8 的 HTML 是调用者的责任;项目 wiki 里列出了几种处理办法。
它能运行在哪些地方?它是一个 Go 库,不是独立应用:你把它链接进任何 Go 程序,Go 能编译的地方它就能用。
作者为什么照着 jQuery 设计 API,而不是自己另起炉灶?因为 jQuery 太流行了,作者觉得一个操作 HTML 的库沿用它的 API 比从零开始更好——就像 Go 的 fmt 包那样的思路——甚至保留了一些不那么直观的方法,比如 index()。
为什么有些方法的名字叫 PrevFiltered 或 FilterNodes 这样的?Go 是静态类型语言,没法像 jQuery 那样把很多重载塞进一个可变参数的方法里,所以每种变体都加了后缀:XxxFiltered 接收选择器字符串,XxxSelection 接收 Selection,XxxNodes 接收 DOM 元素,XxxFunction 接收函数,XxxMatcher 接收编译好的 matcher。
jQuery 的所有选择器在 goquery 里表现都一样吗?不完全一样:cascadia 的选择器不一定覆盖 jQuery(Sizzle)的所有选择器,行为更接近 DOM 的 querySelectorAll,没有上下文匹配。无效的选择器字符串会静默编译成一个什么都不匹配的 Matcher,所以 Find('~') 只会返回一个空的结果集。
API 稳定吗?这个项目还在维护吗?是的——README 声明 API 已稳定,不会破坏兼容性。开发也很活跃:2026 年 8 月发布的 v1.13.0 带来了性能改进、一个类似 BeautifulSoup 的 gettext、支持选项的顶层 Text 函数,以及把 go1.27 加入了测试矩阵。
What are similar projects?cheerio, gjson, jsoup, go, colly, REDox, scrapy, webmagic
Size
0.7 MB
Stars
15K
Age
14y
Commits · 90 Days