goquery.loadhtmlstring直接解析html字符串,需检查err防panic;标签名必须小写,class/id区分大小写;each中勿直接修改节点;text前应移除script/style;静态html外需用chromedp等工具。

用 goquery.LoadHTMLString 解析 HTML 字符串最直接
字符串内容直接进内存解析,不用碰文件或网络,适合模板渲染、爬虫预处理、单元测试等场景。goquery.NewDocumentFromReader 也能用,但需要自己构造 io.Reader,多一层转换容易出错。
常见错误是传入空字符串或非法 UTF-8,goquery.LoadHTMLString 会静默失败(返回 nil 的 *goquery.Document 和非空 error),不检查就 panic。
- 始终检查返回的
err,别只看doc是否为nil - 若 HTML 来自外部(如 HTTP 响应体),先用
strings.TrimSpace去首尾空白,避免因 BOM 或换行导致解析异常 - 中文乱码?确保原始字符串已是 UTF-8 编码;
goquery不做字符集检测和转码
用 Find("a") 选元素时注意 CSS 选择器大小写敏感性
goquery 底层用 golang.org/x/net/html 解析,而 HTML 标签名在 DOM 中是小写的,即使源 HTML 写成 <a href="..."></a>,解析后也统一为 a。所以 Find("A") 永远匹配不到任何链接。
- 所有标签名必须小写:
Find("div")、Find("img"),不是"DIV"或"Img" - class 和 id 匹配区分大小写,
Find(".MyClass")≠Find(".myclass") - 属性选择器如
[href]或[data-id]不受大小写影响,但值匹配仍区分大小写([lang="zh-CN"]不匹配lang="zh-cn")
遍历 .Each() 里别直接改节点结构
.Each(func(i int, s *goquery.Selection) 是常用模式,但很多人在里面调用 s.Append() 或 s.SetHtml(),结果发现只生效最后一次,或 panic:「cannot set html on detached node」。
立即学习“go语言免费学习笔记(深入)”;
-
Each迭代的是当前 Selection 的快照,节点引用可能已脱离文档树,修改无效 - 真要批量改内容,先用
.Map()提取数据,或用.EachWithBreak()+ 显式Selection.Parent().Find(...).ReplaceWith() - 更安全的做法是:用
.Clone()复制节点再操作,或把修改逻辑收拢到单次Find().Each()外部统一处理
中文文本提取用 .Text() 前先 .Contents() 过滤 script/style
.Text() 会把 <script></script> 和 <style></style> 里的代码也当文本拉出来,导致脏数据。比如页面里有 <script>var a = "你好";</script>,.Text() 返回值就含 "var a = \"你好\";"。
- 正确做法是先
doc.Find("script, style").Remove(),再调.Text() - 如果只想取某个容器内纯文本(比如
<article></article>),用selection.Contents().FilterFunction(func(i int, s *goquery.Selection) bool { return s.Nodes[0].Type == html.TextNode })更精准,但性能略低 -
.Text()自动合并相邻文本节点并压缩空白,不需要额外strings.TrimSpace,但换行符保留为\n,不是空格
真正麻烦的是嵌套 iframe 或动态 JS 渲染的内容——goquery 完全看不到,它只解析静态 HTML。这时候得换 Puppeteer 或 Chromedp,而不是硬调 Find。











