goquery为Go语言带来了类似jQuery的语法和一系列功能。它基于Go的net/html包和CSS选择器库cascadia。由于net/html解析器返回的是节点而非完整的DOM树,jQuery的有状态操作函数(如height()、css()、detach())被省略了。
此外,由于net/html解析器要求UTF-8编码,goquery也是如此:确保源文档提供UTF-8编码的HTML是调用者的责任。有关各种实现方法,请参阅wiki。
在语法上,它尽可能接近jQuery,尽可能使用相同的函数名,并保留了那种温暖而模糊的可链式接口。鉴于jQuery是如此流行的库,我觉得编写一个类似的HTML操作库最好遵循其API,而不是重新开始(与Go的fmt包精神相同),尽管它的一些方法不太直观(说的就是你,index()...)。
请注意,从goquery的v1.9.0版本开始,由于使用了泛型,需要Go 1.18+。对于之前的goquery版本,由于net/html依赖,需要Go 1.1+版本。正在进行的goquery开发在最新的两个Go版本上进行测试。
$ go get github.com/PuerkitoBio/goquery
(可选)运行单元测试:
$ cd $GOPATH/src/github.com/PuerkitoBio/goquery
$ go test
(可选)运行基准测试(警告:需要几分钟时间):
$ cd $GOPATH/src/github.com/PuerkitoBio/goquery
$ go test -bench=".*"
请注意,goquery的API现已稳定,不会发生破坏性变更。
go.mod 依赖。Map 函数和 Selection.Map 方法的内存分配和性能,更好地记录cascadia的差异(感谢 @jwilsson)。Map 函数,goquery现在需要Go 1.18+版本(感谢 @Fesaa)。go.mod 依赖,更新CI工作流程。Render 函数,将 Selection 渲染到 io.Writer(感谢 @anthonygedeon)。Single 和 SingleMatcher 函数以优化首次匹配选择(感谢 @gdollardollar)。Selection 上调用 {Prepend,Append,Set}Html 时的崩溃问题。AfterHtml、AppendHtml等)在容器节点的上下文中解析html。感谢 @thiemok 和 @davidjwilkins 的贡献。NewDocumentFromReader 示例。NewDocument(url) 和 NewDocumentFromResponse(response)。Slice 中添加 ToEnd 常量,用于选择到末尾(感谢 @davidjwilkins 提出问题)。AddBack* 并废弃 AndSelf(感谢 @davidjwilkins)。SetHtml 和 SetText(感谢 @glebtv)。Selection.Text 的内存分配(感谢 @radovskyb)。Matcher 实现(而不是引发panic)。例如,doc.Find("~") 返回一个空的 *Selection 对象。NodeName 实用函数,类似于DOM的 nodeName 属性。它返回选择中第一个元素的标签名,以及非元素节点的其他相关值(详见文档)。添加 OuterHtml 实用函数,类似于DOM的 outerHTML 属性(命名为 OuterHtml,小写以保持与现有 Selection 上的 Html 方法一致)。AttrOr 辅助方法,返回属性值或缺失时的默认值。感谢 piotrkowalczuk。*Matcher 函数,接收已编译的cascadia选择器而非选择器字符串,从而避免goquery通过 cascadia.MustCompile 调用可能引发的panic。这提高了性能(选择器可以编译一次并重复使用)并使错误处理更符合惯例(您可以处理cascadia的编译错误,而不是从panic中恢复,这一直困扰着我)。注意,实际期望的类型是 Matcher 接口,cascadia.Selector 实现了该接口。可以使用其他匹配器实现。html.Node 调用goquery时,请确保更新代码以使用新的导入路径。NewDocumentFromReader()(感谢jweir),允许从io.Reader创建goquery文档。NewDocumentFromResponse()(感谢assassingj),允许从http响应创建goquery文档。EachWithBreak(),允许通过返回false来跳出 Each() 循环。添加此函数而不是更改现有的 Each() 以避免破坏兼容性。Document.Root,Document现在本身就是一个Selection(单一选择,即根元素,与之前的Document.Root相同)。添加了jQuery的Closest()方法。与jQuery不同,goquery不是作为DOM文档的一部分加载,也不会作用于包含它的文档。因此,goquery需要被告知要操作哪个HTML文档。这就是Document类型的用途。它持有根文档节点作为初始的Selection值进行操作。
goquery暴露了两个结构体Document和Selection,以及Matcher接口。jQuery通常对同一个函数有多个变体(无参数、选择器字符串参数、jQuery对象参数、DOM元素参数等)。goquery没有使用带有可变空接口参数的单一方法来提供相同的功能,而是使用静态类型的签名,遵循以下命名约定:
Prev()),而带选择器字符串参数的版本称为XxxFiltered()(如PrevFiltered())Is())XxxSelection(),并接受*Selection对象作为参数(如FilterSelection())XxxNodes(),并接受*html.Node类型的可变参数(如FilterNodes())XxxFunction(),并接受一个函数作为参数(如FilterFunction())Matcher接口,定义为XxxMatcher()(如IsMatcher())在jQuery中不存在但在Go中有用的实用函数被实现为函数(接受*Selection作为参数),以避免与*Selection的方法(保留用于jQuery等效行为)可能发生的命名冲突。
完整的包参考文档可以在这里找到。
请注意,Cascadia的选择器不一定匹配jQuery(Sizzle)支持的所有选择器。详情请参见cascadia项目。此外,选择器的工作方式更像DOM的querySelectorAll,而不是jQuery的匹配器 - 它们没有上下文匹配的概念(关于这意味着什么的一些具体例子,请参见此票据)。实践中,这通常不太重要,但值得一提。无效的选择器字符串会编译成一个无法匹配任何节点的Matcher。接受选择 器字符串作为参数的各种函数的行为遵循这一事实,例如(其中~是一个无效的选择器字符串):
Find("~")返回一个空选择,因为选择器字符串不匹配任何内容。Add("~")返回一个新的选择,持有与原始选择相同的节点,因为它没有添加任何节点(选择器字符串不匹配任何内容)。ParentsFiltered("~")返回一个空选择,因为选择器字符串不匹配任何内容。ParentsUntil("~")返回选择的所有父元素,因为选择器字符串没有匹配到任何元素来停止在顶层元素之前。在wiki中查看一些技巧和窍门。
改编自example_test.go:
package main import ( "fmt" "log" "net/http" "github.com/PuerkitoBio/goquery" ) func ExampleScrape() { // 请求HTML页面 res, err := http.Get("http://metalsucks.net") if err != nil { log.Fatal(err) } defer res.Body.Close() if res.StatusCode != 200 { log.Fatalf("状态码错误: %d %s", res.StatusCode, res.Status) } // 加载HTML文档 doc, err := goquery.NewDocumentFromReader(res.Body) if err != nil { log.Fatal(err) } // 查找评论项目 doc.Find(".left-content article .post-title").Each(func(i int, s *goquery.Selection) { // 对于找到的每个项目,获取标题 title := s.Find("a").Text() fmt.Printf("评论 %d: %s\n", i, title) }) } func main() { ExampleScrape() }
您可以通过以下几种方式支持本项目:
<a href="https://www.buymeacoffee.com/mna" target="_blank"><img src="https://yellow-cdn.veclightyear.com/835a84d5/48cb6fbe-9bd6-482f-9c6d-aed4be48af82.png" alt="Buy Me A Coffee" style="height: 41px !important;width: 174px !important;box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;-webkit-box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;" ></a>
BSD 3-Clause许可证,与Go语言相同。Cascadia的许可证在这里。


免费创建高清无水印Sora视频
Vora是一个免费创建高清无水印Sora视频的AI工具


最适合小白的AI自动化工作流平台
无需编码,轻松生成可复用、可变现的AI自动化工作流

大模型驱动的Excel数据处理工具
基于大模型交互的表格处理系统,允许用户通过对话方式完成数据整理和可视化分析。系统采用机器学习算法解析用户指令,自动执行排序、公式计算和数据透视等操作,支持多种文件格式导入导出。数据处理响应速度保持在0.8秒以内,支持超过100万行数据的即时分析。


AI辅助编程,代码自动修复
Trae是一种自适应的集成开发环境(IDE),通过自动化和多元协作改变开发流程。利用Trae,团队能够更快速、精确地编写和部署代码,从而提高编程效率和项目交付速度。Trae具备上下文感知和代码自动完成功能,是提升开发效率的理想工具。


AI论文写作指导平台
AIWritePaper论文写作是一站式AI论文写作辅助工具,简化了选题、文献检索至论文撰写的整个过程。通过简单设定,平台可快速生成高质量论文大纲和全文,配合图表、参考文献等一应俱全,同时提供开题报告和答辩PPT等增值服务,保障数据安全,有效提升写作效率和论文质量。


AI一键生成PPT,就用博思AIPPT!
博思AIPPT,新一代的AI生成PPT平台,支持智能生成PPT、AI美化PPT、文本&链接生成PPT、导入Word/PDF/Markdown文档生成PPT等,内置海量精美PPT模板,涵盖商务、教育、科技等不同风格,同时针对每个页面提供多种版式,一键自适应切换,完美适配各种办公场景。


AI赋能电商视觉革命,一站式智能商拍平台
潮际好麦深耕服装行业,是国内AI试衣效果最好的软件。使用先进AIGC能力为电商卖家批量提供优质的、低成本的商拍图。合作品牌有Shein、Lazada、安踏、百丽等65个国内外头部品牌,以及国内10万+淘宝、天猫、京东等主流平台的品牌商家,为卖家节省将近85%的出图成本, 提升约3倍出图效率,让品牌能够快速上架。


企业专属的AI法律顾问
iTerms是法大大集团旗下法律子品牌,基于最先进的大语言模型(LLM)、专业的法律知识库和强大的智能体架构,帮助企业扫清合规障碍,筑牢风控防线,成为您企业专属的AI法律顾问。


稳定高效的流量提升解决方案,助力品牌曝光
稳定高效的流量提升解决方案,助力品牌曝光


最新版Sora2模型免费使用,一键生成无水印视频
最新版Sora2模型免费使用, 一键生成无水印视频
最新AI工具、AI资讯
独家AI资源、AI项目落地

微信扫一扫关注公众号