前言
在解析、抓取html中部分数据时,为了快速定位数据,难免要使用jQuery相关。
在Go中有个实现类似jQuery功能的库,那就是goquery
。
本文主要介绍下goquery初步使用,尤其是对jQuery不熟的情况下,先对goquery有个初步的了解。
更多内容分享,欢迎关注公众号:Go开发笔记
goquery
goquery是基于Go标准库net/html
及css选择器cascadia的基础实现的。
由于 net/html 解析器返回Node,而不是功能齐全的DOM树,jQuery的有状态操作函数(如height(), css(), detach())不支持。另外,net/html仅支持UTF-8编码,goquery也需要UTF-8编码,也就是说在使用goquery前,如果html的编码不是UTF-8,需要先对数据进行编码转换
。在语法方面,goquery也尽可能地与jQuery使用相同的函数名。
goquery对外暴露两个struct:Document
和Selection
,一个interface:Matcher
。与 jQuery 不同,jQuery 作为 DOM 文档的一部分加载,因此对包含的文档进行行为,goquery 不知道要对哪个 HTML 文档进行操作。因此,它需要被告知Document。它持有根文档节点作为要操作的初始Selection值。
jQuery 通常具有同一函数的许多变体(无参数、selector字符串参数、jQuery 对象参数、DOM 元素参数等)。为了在goquery中公开具有可变空接口参数的同样特性的单个方法,按照以下命名约定使用静态类型标识:
-
当 jQuery 等效项没有参数可以被调用时,它具有与无参数标识的 jQuery 相同的名称(例如:Prev()),并且具有一个selector字符串参数的版本称为
XxxFiltered()
(例如:PrevFiltered()
) -
当 jQuery 等效项需要一个参数时,selector字符串版本使用与 jQuery 相同的名称(例如:
Is()
) -
接受 jQuery 对象作为参数的标,在 goquery 中定义为
XxxSelection()
,并且将*Selection
对象作为参数(例如:FilterSelection()
) -
在 jQuery 中接受 DOM 元素作为参数的标识,在 goquery 中定义为
XxxNodes()
,并具有类型的可变参数*html.Node
(例如:FilterNodes()
) -
在 jQuery 中接受函数作为参数的标识,在 goquery 中定义为
XxxFunction()
,并且将函数作为参数(例如:FilterFunction()
) -
可以用selector字符串调用的goquery方法有一个对应的版本,该版本采用
Matcher
接口,定义为XxxMatcher()
-
不在 jQuery 中但在 Go 中有用的实用程序函数作为函数实现(以
*Selection
为参数),以避免*Selection
方法上的潜在命名冲突(为 jQuery 等效行为保留)。
安装
go get github.com/PuerkitoBio/goquery
使用go mod
require github.com/PuerkitoBio/goquery latest
使用
为了更简单的说明goquery的使用,我们以查找html中指定ul中的img为例,核心html内容如下:
<ul id="Ul_NAME" class="tt-thumb tt-clear">
<li class="">
<a href="#"><img src="xx0.jpg" /></a>
</li>
<li class="tb-selected">
<a href="#"><img src="xx1.jpg" /></a>
</li>
<li class="">
<a href="#"><img src="xx2.jpg" /></a>
</li>
...
</ul>
1.加载HTML document——NewDocumentFromReader
func NewDocumentFromReader(r io.Reader) (*Document, error)
通过io.Reader接口,可以加载本地/网络的html文档。
从网络加载示例如下:
// 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)
}
2.查找——Find
func (s *Selection) Find(selector string) *Selection
selector可以参考jQuery的使用
如果通过class查找,可以使用:
selector := “.tt-thumb.tt-clear li a img”
注意:如果class中存在空格,以.
代替。
如果通过id查找则可以使用:
selector := “ul#Ul_NAME li a img”
使用id需要标明类型,并以#
隔开。
使用示例:
doc.Find(selector)
3.匹配结果——Selection
func (s *Selection) Each(f func(int, *Selection)) *Selection
查找匹配后可能会有多个数据,使用Each可以迭代处理每个数据。
4.获取具体的属性——Attr
func (s *Selection) Attr(attrName string) (val string, exists bool)
要获取src,使用如下:
img, ok := selection.Attr("src")
5.完整示例:
// Request the HTML page.
res, err := http.Get("http://xx.com")
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
var imgs []string
doc.Find("ul#Ul_NAME li a img").Each(func(i int, selection *goquery.Selection) {
img, _ := selection.Attr("src")
if img!="" {
imgs = append(imgs,img)
}
}
// Handle imgs
...
总结
本文主要介绍了goquery与jQuery的对照规则,以及从一个例子简单的说明goquery的使用。更深入的使用可以先从jQuery入手,熟悉jQuery后可以更熟练地使用goquery。
公众号
鄙人刚刚开通了公众号,专注于分享Go开发相关内容,望大家感兴趣的支持一下,在此特别感谢。