[日常] Go语言圣经-匿名函数习题2

练习5.13: 修改crawl,使其能保存发现的页面,必要时,可以创建目录来保存这些页面。只保存来自原始域名下的页面。假设初始页面在golang.org下,就不
要保存vimeo.com下的页面。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
package main
 
import (
        "fmt"
        "io"
        "io/ioutil"
        "links"
        "log"
        "net/http"
        "net/url"
        "os"
)
/*
练习5.13: 修改crawl,使其能保存发现的页面,必要时,可以创建目录来保存这些页面。只保存来自原始域名下的页面。假设初始页面在golang.org下,就不要保存vimeo.com下的页面。
*/
var sum int
func main() {
        breadthFirst(crawl, os.Args[1:])
}
 
/*
抓取页面的所有连接
*/
func crawl(url string) []string {
        sum++
 
        go save(url)
        fmt.Printf("%d|%s\n", sum, url)
        list, err := links.Extract(url)
        if err != nil {
                log.Print(err)
        }
        return list
}
 
/*
保存页面到文件
*/
func save(u string) bool {
 
        urlObj, _ := url.Parse(u)
        path := "/tmp/crawl/" + urlObj.Host
        if urlObj.Path == "" || urlObj.Path == "/" {
                urlObj.Path = "/index.html"
        }
        filename := path + urlObj.Path //重点注意文件名
        fmt.Println(filename)
        //打开文件
        f, _ := os.OpenFile(filename, os.O_CREATE|os.O_APPEND|os.O_RDWR, 0755)
        //读取链接
        resp, geterr := http.Get(u)
 
        if geterr != nil || resp.StatusCode != http.StatusOK {
                //resp.Body.Close()
                return false
        }
        body, _ := ioutil.ReadAll(resp.Body)
        //fmt.Println(body)
        //创建保存目录
        _, err := os.Stat(path)
        if err != nil {
                os.MkdirAll(path, 0755)
        }
 
        io.WriteString(f, string(body))
        resp.Body.Close()
        body = nil
        return true
}
 
/*
广度优先算法
*/
// breadthFirst calls f for each item in the worklist.
// Any items returned by f are added to the worklist.
// f is called at most once for each item.
func breadthFirst(f func(item string) []string, worklist []string) {
        seen := make(map[string]bool)
        for len(worklist) > 0 {
                items := worklist
                worklist = nil
                for _, item := range items {
                        if !seen[item] {
                                seen[item] = true
                                worklist = append(worklist, f(item)...)
                        }
                }
        }
}

  

posted @   唯一客服系统开发笔记  阅读(335)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
历史上的今天:
2016-04-18 [android] 用fragment创建一个选项卡
2016-04-18 [android] fragment的动态创建
2016-04-18 [Python] 函数基本
2016-04-18 [Python] 使用dict和set
点击右上角即可分享
微信分享提示
1
chat with us