为什么这个程序不能打印任何东西?

时间:2017-02-24 12:56:37

标签: html parsing go

我试图使用Go来解析HTML。我想将html打印到终端,我不明白为什么这不会打印任何东西:

package main

import (
        "fmt"
        "log"
        "net/http"

        "golang.org/x/net/html"
)

func main() {
        r, err := http.Get("https://google.com")
        if err != nil {
                log.Panicln(err)
        }

        defer func() {
                err := r.Body.Close()
                if err != nil {
                        fmt.Println(err)
                }
        }()

        node, err := html.Parse(r.Body)
        if err != nil {
                log.Panicln(err)
        }
        fmt.Println(node.Data)
}

我知道有不同的方法来打印html,但我不明白为什么这个特别是从来没有打印任何东西,无论我使用什么网站。这是预期的行为吗?

文档:

https://godoc.org/golang.org/x/net/html#Node

https://github.com/golang/net/blob/master/html/node.go#L38

2 个答案:

答案 0 :(得分:2)

因为它是HTML的树。上层是空的。 例如,如果您需要解析来自html的所有网址:

package main

import (
        "fmt"
        "log"
        "net/http"

        "golang.org/x/net/html"
)

func main() {
        r, err := http.Get("https://google.com")
        if err != nil {
                log.Panicln(err)
        }

        defer func() {
                err := r.Body.Close()
                if err != nil {
                        fmt.Println(err)
                }
        }()

        node, err := html.Parse(r.Body)
        if err != nil {
                log.Panicln(err)
        }
        fmt.Println(node.Data)

        var f func(*html.Node)
        f = func(n *html.Node) {
            if n.Type == html.ElementNode && n.Data == "a" {
                for _, a := range n.Attr {
                    if a.Key == "href" {
                        fmt.Println(a.Val)
                        break
                    }
                }
            }
            for c := n.FirstChild; c != nil; c = c.NextSibling {
                f(c)
            }
        }
        f(node)
}

答案 1 :(得分:2)

这是因为html.Parse返回连接节点的树。并且根节点的类型为" document"里面没有数据。

如何走树的简单示例:

package main

import (
    "fmt"
    "golang.org/x/net/html"
    "strings"

)

func nodeTypeAsString(nodeType html.NodeType) string{
    switch(nodeType){
    case html.ErrorNode : return "ErrorNode"
    case html.TextNode : return "TextNode"
    case html.DocumentNode : return "DocumentNode"
    case html.ElementNode : return "ElementNode"
    case html.CommentNode : return "CommentNode"
    case html.DoctypeNode: return  "DoctypeNode"
    }
    return "UNKNOWN"
}

func main() {
    s := "<html><body><p>Some content</p></body></html>"
    node, err := html.Parse(strings.NewReader(s))
    if err != nil {
        panic(err.Error())
    }

    // Root node
    fmt.Printf("NodeType=%s Data=%s\n",nodeTypeAsString(node.Type),node.Data)
    // Step deeper
    node = node.FirstChild
    fmt.Printf("NodeType=%s Data=%s\n",nodeTypeAsString(node.Type),node.Data)
    // Step deeper
    node = node.FirstChild
    fmt.Printf("NodeType=%s Data=%s\n",nodeTypeAsString(node.Type),node.Data)
    // Step over to sibling
    node = node.NextSibling
    fmt.Printf("NodeType=%s Data=%s\n",nodeTypeAsString(node.Type),node.Data)
    // Step deeper
    node = node.FirstChild
    fmt.Printf("NodeType=%s Data=%s\n",nodeTypeAsString(node.Type),node.Data)
    // Step deeper
    node = node.FirstChild
    fmt.Printf("NodeType=%s Data=%s\n",nodeTypeAsString(node.Type),node.Data)
}

输出:

NodeType=DocumentNode Data=
NodeType=ElementNode Data=html
NodeType=ElementNode Data=head
NodeType=ElementNode Data=body
NodeType=ElementNode Data=p
NodeType=TextNode Data=Some content