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

问题描述:

我正在尝试使用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

+0

尝试检查 '节点' 的内容。看看它是什么类型等等。[go-spew](https://github.com/davecgh/go-spew)可以帮助解决这个问题。我怀疑node.Data没有包含任何内容,并且可能有很好的理由。 – Flimzy

,因为它是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) 
} 

这是因为html.Parse返回连接节点的树。而根节点的类型是“文档”,里面没有数据。如何走树

简单的例子:

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) 
} 

OUTPUT:

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