假设我有一个包含
之类的html页面<ul class ="good">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<ul class ="bad">
<li>a</li>
<li>b</li>
<li>c</li>
</ul>
我想抓住第一个<li>
内的<ul>
元素。从here我基本上复制了(注意:每个@twotwotwo评论编辑的代码)
page, _ := html.Parse(httpBody)
var f func(*html.Node)
f = func(n *html.Node) {
//fmt.Println("Inside f")
if n.Type == html.ElementNode && n.Data == "ul" {
fmt.Println("ul found -> ",n)
for c := n.FirstChild; c != nil; c = c.NextSibling {
f(c)
}
} else {
fmt.Println(n.Data ,"is not the correct one")
for c := n.FirstChild; c != nil; c = c.NextSibling { f(c) }
}
}
f(page)
但我获得的唯一输出是
is not the correct one
html is not the correct one
head is not the correct one
body is not the correct one
我想知道为什么递归停止在身体上。我试过motherfuckingwebsite.com,身体里面有标签
P.S。 我也试过
page := html.NewTokenizer(httpBody)
for {
tokenType := page.Next()
if tokenType == html.ErrorToken {
return links
}
token := page.Token()
但这似乎显示了所有的令牌,而不关心树的结构。
修改
答案 0 :(得分:4)
过去,我使用过这个包:https://github.com/PuerkitoBio/goquery
它提供了一个“类似jQuery”的界面/查询HTML文档。使用该库,它就像这样简单:
import (
"bytes"
"fmt"
"log"
"github.com/PuerkitoBio/goquery"
)
var httpBody string = `
<ul class ="good">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<ul class ="bad">
<li>a</li>
<li>b</li>
<li>c</li>
</ul>
`
func main() {
b := bytes.NewBufferString(httpBody)
doc, err := goquery.NewDocumentFromReader(b)
if err != nil {
log.Fatal(err)
}
doc.Find("ul.good").Each(func(i int, ul *goquery.Selection) {
ul.Find("li").Each(func(i int, li *goquery.Selection) {
fmt.Println(li.Text())
})
})
}
打印哪些:
1
2
3