广度优先配合匿名函数爬取

哆啦在这A梦在哪 · · 235 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

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.如果使用了上述情况,在广度优先遍历的时候,内部使用递归调用,在接收返回值的时候,会很麻烦,每一次都调用一个函数,每个函数又都返回一个值,暂时没想到怎么接收,如果有人看到这篇文章,能给一些建议,本人万分感谢


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:哆啦在这A梦在哪

查看原文:广度优先配合匿名函数爬取

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:1006366459

235 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传