必须先调用 html.Parse() 或 html.ParseFragment() 构建 DOM 树,不可直接操作 html.Node;Parse 用于完整 HTML 文档,需 io.Reader 输入;ParseFragment 适用于 HTML 片段。

用 net/html 解析 HTML 时,必须先调用 html.Parse() 获取根节点
直接对原始 HTML 字符串调用 html.Node 相关操作会 panic,因为没有解析器上下文。必须先通过 html.Parse() 或 html.ParseFragment() 构建 DOM 树。
-
html.Parse()用于完整 HTML 文档(含、等),输入需是io.Reader,常见用法:doc, err := html.Parse(strings.NewReader(htmlStr)) if err != nil { log.Fatal(err) } -
html.ParseFragment()适合解析片段(如仅),需传入一个“上下文节点”(如...&html.Node{Type: html.ElementNode, Data: "body"}),否则可能丢节点或 panic - 注意:解析器不校验编码,默认按 UTF-8 处理;若 HTML 声明为
gbk或utf-8但实际字节非 UTF-8,会读出乱码甚至提前截断
遍历节点时,node.Type 比 node.Data 更可靠
很多新手误以为查 node.Data == "div" 就能定位元素,但 Data 在不同 Type 下含义不同:文本节点存内容,注释节点存注释文字,元素节点才存标签名。漏判 Type 会导致逻辑错位或空指针。
- 关键类型常量:
html.ElementNode(标签)、html.TextNode(文本)、html.CommentNode(注释)、html.DoctypeNode(doctype) - 安全遍历示例:
func findDivs(n *html.Node) { if n.Type == html.ElementNode && n.Data == "div" { // 处理 div 元素 fmt.Println("found div") } for c := n.FirstChild; c != nil; c = c.NextSibling { findDivs(c) } } - 不要依赖
n.DataAtom—— 它是内部优化字段,未导出且仅在特定构建下有效,跨平台或新版 Go 可能失效
node.Attr 是切片,查属性必须遍历,没有 GetAttribute() 这种方法
Go 的 net/html 不提供类似 jQuery 的 attr("href") 便捷接口,所有属性访问都得手动循环 node.Attr 切片比对 Key。
- 常见错误:写成
node.Attr["href"]—— 编译失败,因为Attr是[]html.Attribute类型,不是 map - 正确写法:
func getHref(n *html.Node) (href string) { for _, a := range n.Attr { if a.Key == "href" { href = a.Val break } } return href } - 注意大小写:HTML 属性名不区分大小写,但
net/html不做归一化,"HREF"和"href"被视为不同 key;生产环境建议统一转小写再比较
解析后不调用 html.Render() 就无法还原 HTML 字符串
如果你从网页提取结构后想拼回 HTML 片段(比如清洗后重新生成),不能靠字符串拼接,必须用 html.Render() 写入 io.Writer。否则丢失转义、闭合逻辑、自闭合标签处理(如 )等细节。
立即学习“go语言免费学习笔记(深入)”;
-
html.Render()会自动处理特殊字符转义(如→zuojiankuohaophpcn)、标签闭合、空白压缩策略(取决于节点类型) - 简单还原示例:
var buf bytes.Buffer err := html.Render(&buf, doc) if err != nil { log.Fatal(err) } htmlOut := buf.String() // 此时才是合法可渲染的 HTML - 注意:若只取部分子树(如某个 ),要确保其作为独立片段可渲染 —— 比如
子节点单独 render 可能缺
,浏览器容错强,但服务端处理时需留意 解析 HTML 最容易被忽略的是编码推断和错误恢复机制:net/html在遇到非法嵌套(如)时会自动修复 DOM 结构,这和浏览器一致,但也意味着你写的 XPath 或层级假设可能在意外情况下失效。











