1 回答
TA贡献1765条经验 获得超5个赞
您的代码不起作用,因为它采用文档的第一个子元素,即元素,然后它采用其同级元素,从而导致函数以空的链接片结尾。htmlnil
详细解释:下面是一个示例代码,
package main
import (
"fmt"
"log"
"strings"
"golang.org/x/net/html"
)
var i int = 0
func visit(links []string, n *html.Node) []string {
if n == nil {
return links
}
if n.Type == html.ElementNode && n.Data == "a" {
for _, a := range n.Attr {
if a.Key == "href" {
links = append(links, a.Val)
}
}
}
if i == 0 {
i++
return visit(links, n.FirstChild)
}
return visit(links, n.NextSibling)
}
func main() {
s := `<p>Links:</p><ul><li><a href="foo">Foo</a><li><a href="/bar/baz">BarBaz</a></ul>`
doc, err := html.Parse(strings.NewReader(s))
if err != nil {
log.Fatal(err)
}
links := visit([]string{}, doc)
fmt.Println(links)
}
第一次调用访问,
参数:
链接 = []
n = DocumentNode
在第一次调用中,i=0,因此它使用文档节点的第一个子节点进行递归调用。visit
第二次访问调用,
参数:
链接 = []
n = ElementNode (n.Data = “html”)
在第二次调用中,是元素节点。现在,对 元素节点的下一个同级节点进行第三次调用。这就是问题所在。元素节点没有同级,因此将是 。nhtmlvisithtmlhtmlnnil
第三次调用访问,
参数:
链接 = []
n = nil
因此,现在所有以递归方式调用的函数 3 函数调用都将返回,并且执行流将返回到,因此切片将保持为空。mainlinks
希望您理解。
编写此功能的正确方法是通过您在问题中共享的循环,如下所示,
package main
import (
"fmt"
"log"
"strings"
"golang.org/x/net/html"
)
func visit(links []string, n *html.Node) []string {
if n.Type == html.ElementNode && n.Data == "a" {
for _, a := range n.Attr {
if a.Key == "href" {
links = append(links, a.Val)
}
}
}
for c := n.FirstChild; c != nil; c = c.NextSibling {
links = visit(links, c)
}
return links
}
func main() {
s := `<p>Links:</p><ul><li><a href="foo">Foo</a><li><a href="/bar/baz">BarBaz</a></ul>`
doc, err := html.Parse(strings.NewReader(s))
if err != nil {
log.Fatal(err)
}
links := visit([]string{}, doc)
fmt.Println(links)
}
在这里,循环通过检查每个HTML元素的子元素来帮助递归地查找链接。如果其中一个HTML元素没有同级元素,那么它将简单地移动到其父级的下一个同级元素并检查
- 1 回答
- 0 关注
- 78 浏览
添加回答
举报