HTML - 查找给定标记中的所有子标记

时间:2014-10-01 02:50:30

标签: html go

假设我有一个包含

之类的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()

但这似乎显示了所有的令牌,而不关心树的结构。

修改

1 个答案:

答案 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