廣度優先配合匿名函數爬取

來源:互聯網
上載者:User

package main

import (

    "fmt"

    "log"

    "net/http"

    "os"

    "golang.org/x/net/html"

)

var (

    str string = "https://docs.hacknode.org/gopl-zh/"

)

//CreatFile is a func ti make infomation in file

func CreatFile(bt []byte) {

    f, err := os.OpenFile("F:/MyGo/src/practice/url.txt", os.O_CREATE|os.O_APPEND, 0666)

    if err != nil {

        log.Fatal(err)

    }

    defer f.Close()

    res, err := f.Write([]byte(bt))

    if err != nil {

        log.Fatal(err)

    }

    if res == 0 {

        fmt.Println("no one")

    }

}

//GetURLInfomation is a func get URL infomation

func GetURLInfomation(URL string) []string {

    resp, err := http.Get(URL)

    if err != nil {

        log.Fatal(err)

    }

    defer resp.Body.Close()

    if resp.StatusCode != http.StatusOK {//判斷狀態

        log.Fatal("Can't connect")

    }

    //開始節點處理

    doc, err := html.Parse(resp.Body)

    if err != nil {

        log.Fatal(err)

    }

    var links []string

    ForOneNode := func(n *html.Node) { 

//匿名函數,單次節點處理,為什麼使用匿名函數,在下面講解

        if n.Type == html.ElementNode && n.Data == "a" {//判斷是否為節點,節點為<a>標籤

            for _, a := range n.Attr {//遍曆標籤屬性

                if a.Key != "href" {

                    continue

                }

                link, err := resp.Request.URL.Parse(a.Val)//解析出URL地址,即屬性內容

                if err != nil {

                    log.Fatal(err)

                }

                links = append(links, link.String())

            }

        }

    }

    ForEachNode(doc, ForOneNode, nil)//遍曆開始


    return links

}

//ForEachNode is 廣度優先遍曆

func ForEachNode(n *html.Node, pre, post func(n *html.Node)) {

    if pre != nil {

        pre(n)

    }

    for c := n.FirstChild; c != nil; c = c.NextSibling {

        ForEachNode(c, pre, post)

    }

    if post != nil {

        post(n)

    }

}

func main() {

    bt := GetURLInfomation("https://docs.hacknode.org/gopl-zh/")

    for _, t := range bt {

        t += "\n"

        CreatFile([]byte(t))

    }

    //CreatFile(bt)

}

註:為什麼使用匿名函數

1.在函數體內,需要將取到的值進行保留,如果使用return函數返回,函數內還要使用到*http.respone類型的變數,在遞迴調用的時候,參數會很繁雜

2.如果使用了上述情況,在廣度優先遍曆的時候,內部使用遞迴調用,在接收傳回值的時候,會很麻煩,每一次都調用一個函數,每個函數又都返回一個值,暫時沒想到怎麼接收,如果有人看到這篇文章,能給一些建議,本人萬分感謝

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.