
本文介绍在 go 中可靠提取 wikipedia 页面 infobox 数据的实用方法,涵盖正则解析技巧、嵌套模板处理难点,并推荐基于 mediawiki api 的稳健方案。
本文介绍在 go 中可靠提取 wikipedia 页面 infobox 数据的实用方法,涵盖正则解析技巧、嵌套模板处理难点,并推荐基于 mediawiki api 的稳健方案。
Wikipedia 的 Infobox 是结构化元数据的核心载体,但其 Wikitext 格式高度嵌套、存在多行值、嵌套模板(如 {{Plainlist|...}}、{{Birth date|...}})和不规则缩进,直接用简单正则匹配极易失败。你提供的示例中,regexp.MustCompile({{Infobox(?s:.?)}}) 无法正确闭合,是因为 Wikitext 中 {{...}} 支持任意深度嵌套(如 {{A|{{B|c}}}}),而 Go 的 regexp 包不支持递归正则((?1))或平衡组,因此 `(?={Infobox)({([^{}]|(?1))})` 会编译失败。
✅ 正确思路应分两步:先精准提取整个 Infobox 块,再逐行解析字段。以下为生产可用的 Go 实现:
1. 安全提取 Infobox 块(支持嵌套)
使用栈模拟括号匹配,避免正则局限:
func extractInfobox(text string) (string, bool) {
var stack []rune
start := -1
for i, r := range text {
switch r {
case '{':
stack = append(stack, r)
if len(stack) == 1 && i+1 0 && stack[len(stack)-1] == '{' {
stack = stack[:len(stack)-1]
if len(stack) == 0 && start >= 0 {
return text[start : i+1], true
}
}
}
}
return "", false
}
2. 解析 Infobox 字段(兼容多行与 Plainlist)
对提取出的块按行处理,识别 | key = value 模式,并合并后续缩进行:
func parseInfoboxBlock(block string) map[string]string {
result := make(map[string]string)
lines := strings.Split(block, "\n")
for i := 0; i <h3>3. 完整调用示例</h3><pre class="brush:php;toolbar:false;">func main() {
st := `{{redirect|Einstein|...}} ... {{Infobox scientist | name = Albert Einstein | ... }} ...`
if block, ok := extractInfobox(st); ok {
data := parseInfoboxBlock(block)
fmt.Printf("Name: %s\n", data["name"]) // "Albert Einstein"
fmt.Printf("Birth date: %s\n", data["birth_date"]) // "{{Birth date|df=yes|1879|3|14}}"
fmt.Printf("Fields: %s\n", data["fields"]) // "Physics, philosophy"
} else {
log.Println("Infobox not found")
}
}⚠️ 重要注意事项:
- 模板未展开:上述方法返回的是原始 Wikitext(如 {{Birth date|...}}),若需解析为标准日期,需额外调用 MediaWiki API 的 action=parse 接口渲染。
-
API 更推荐:直接通过 MediaWiki API 获取解析后 HTML 或 Wikitext:
# 获取纯文本 Infobox(需指定 prop=extracts&exintro&explaintext) curl "https://www.php.cn/link/f86194e5108223325e2c43aa0997bb80?action=query&titles=Albert%20Einstein&prop=extracts&exintro&explaintext&format=json"
或使用 prop=revisions&rvprop=content 获取原始 Wikitext,再用上述 Go 函数解析——这比网页爬取更稳定、合规。
- 结构差异:不同 Infobox 模板(Infobox scientist、Infobox person)字段名不同,建议动态键名而非硬编码 struct。
综上,放弃“单正则匹配全部”的幻想,采用“栈提取 + 行解析”组合策略,配合 MediaWiki 官方 API,是 Go 生态中解析 Wikipedia Infobox 最务实、可维护的方案。











