亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

涉及 *html 的遞歸函數。用于打印 HTML 文檔中所有鏈接的節點

涉及 *html 的遞歸函數。用于打印 HTML 文檔中所有鏈接的節點

Go
桃花長相依 2022-08-30 15:01:07
我正在嘗試使用接受*html的函數打印HTML文檔中的所有鏈接。節點作為參數。我是Golang和*html的新手。節點數據類型,我以前從未使用過它們。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)}檢查是否的 if 塊的目的是確保只運行一次(第一次)并在后續迭代中運行。但是,從不追加,并且始終返回空切片。我不明白代碼中的錯誤。i==0return visit(links, n.FirstChild)return visit(links, n.NextSibling)links使用 for 循環時,代碼工作正常,但當我嘗試使用遞歸時,代碼會中斷。for c := n.FirstChild; c != nil; c = c.NextSibling {        links = visit(links, c)    }
查看完整描述

1 回答

?
POPMUISE

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元素沒有同級元素,那么它將簡單地移動到其父級的下一個同級元素并檢查


查看完整回答
反對 回復 2022-08-30
  • 1 回答
  • 0 關注
  • 92 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號