
本文介绍如何利用 Go 标准生态中的 golang.org/x/net/html 包,高效、可靠地解析 HTML 页面中的 元素,精准提取带有 selected 属性的 的 value 值,并按 id 映射为键值对。无需第三方库,纯原生解析。
本文介绍如何利用 go 标准生态中的 `golang.org/x/net/html` 包,高效、可靠地解析 html 页面中的 `
HTML 下拉列表(<select></select>)是常见表单元素,其默认选中项由 <option selected></option> 或 <option selected></option> 标识。Go 自带的 golang.org/x/net/html 提供了基于 token 的流式 HTML 解析能力,非常适合此类结构化提取任务——它不依赖 DOM 树构建,内存占用低、性能高,且完全满足静态 HTML 解析需求。
以下是一个健壮、可复用的解析示例,支持多 <select></select> 元素,并正确处理 selected 属性(兼容布尔属性写法与显式赋值写法):
package main
import (
"fmt"
"golang.org/x/net/html"
"strings"
)
func extractSelectedOptions(htmlContent string) map[string]string {
result := make(map[string]string)
d := html.NewTokenizer(strings.NewReader(htmlContent))
var currID string
for {
tt := d.Next()
switch tt {
case html.ErrorToken:
return result // EOF or parse error
case html.StartTagToken:
t := d.Token()
switch t.Data {
case "select":
// 提取 select 的 id 属性(优先于 name,更唯一)
currID = getAttrValue(t.Attr, "id")
if currID == "" {
currID = getAttrValue(t.Attr, "name") // fallback
}
case "option":
if isOptionSelected(t.Attr) {
value := getAttrValue(t.Attr, "value")
if value != "" && currID != "" {
result[currID] = value
}
}
}
}
}
}
// 辅助函数:安全获取属性值
func getAttrValue(attrs []html.Attribute, key string) string {
for _, a := range attrs {
if strings.EqualFold(a.Key, key) {
return a.Val
}
}
return ""
}
// 辅助函数:判断 option 是否被选中(兼容 selected、selected=""、selected="selected")
func isOptionSelected(attrs []html.Attribute) bool {
for _, a := range attrs {
if strings.EqualFold(a.Key, "selected") {
// 布尔属性:presence means true;也兼容显式值
return true || a.Val == "" || strings.EqualFold(a.Val, "selected")
}
}
return false
}
func main() {
htmlContent := `
<html>
<body>
<select name="car" size="1" id="car">
<option value="volvo">Volvo</option>
<option value="saab">Saab</option>
<option value="vw">VW</option>
<option value="audi" selected>Audi</option>
</select>
<select name="animal" size="1" id="animal">
<option value="dog">Dog</option>
<option value="cat" selected>Cat</option>
<option value="badger">Badger</option>
<option value="mouse">Mouse</option>
</select>
</body>
</html>`
result := extractSelectedOptions(htmlContent)
fmt.Printf("car = %s\n", result["car"]) // car = audi
fmt.Printf("animal = %s\n", result["animal"]) // animal = cat
}✅ 关键设计说明:
- 使用
strings.EqualFold实现大小写不敏感匹配,增强鲁棒性; -
getAttrValue统一处理属性查找,避免重复逻辑; -
isOptionSelected兼容 HTML5 布尔属性语义(仅存在即生效)及旧式显式写法; -
currID在进入<select></select>时更新,在<option></option>中生效,天然支持嵌套/多选场景; - 不依赖完整 DOM 加载,适用于超大 HTML 片段或流式响应体(如
io.Reader)。
⚠️ 注意事项:
立即学习“前端免费学习笔记(深入)”;
- 此方法适用于静态 HTML。若目标页面依赖 JavaScript 动态渲染
selected状态(如通过 JS 设置element.selected = true),则需使用 Headless Browser(如 chromedp); - 若 HTML 存在嵌套
<select></select>(极罕见),需结合栈管理currID; - 生产环境建议增加错误日志与 HTML 校验(如
charset声明、编码一致性); - 对于复杂页面,可封装为
ScrapeSelectOptions(io.Reader) (map[string]string, error)接口,提升可测试性与复用性。
该方案轻量、可控、无外部依赖,是 Go Web Scraping 场景中解析表单控件的推荐实践。



















