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

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)...)
}
}
}
}

  

[日常] Go语言圣经-匿名函数习题2的更多相关文章

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

    Go语言圣经-匿名函数1.拥有函数名的函数只能在包级语法块中被声明,通过函数字面量(function literal),我们可绕过这一限制,在任何表达式中表示一个函数值2.通过这种方式定义的函数可以访 ...

  2. [日常] Go语言圣经-错误,函数值习题

    Go语言圣经-错误 1.panic异常.panic是来自被调函数的信号,表示发生了某个已知的bug 2.任何进行I/O操作的函数都会面临出现错误的可能 3.错误是软件包API和应用程序用户界面的一个重 ...

  3. [日常] Go语言圣经--接口约定习题

    Go语言圣经-接口1.接口类型是对其它类型行为的抽象和概括2.Go语言中接口类型的独特之处在于它是满足隐式实现的3.Go语言中还存在着另外一种类型:接口类型.接口类型是一种抽象的类型4.一个类型可以自 ...

  4. [日常] Go语言圣经-Deferred函数

    1.只需要在调用普通函数或方法前加上关键字defer,就完成了defer所需要的语法.当defer语句被执行时,跟在defer后面的函数会被延迟执行.直到包含该defer语句的函数执行完毕时,defe ...

  5. [日常] Go语言圣经-竞争条件习题

    package main import( "fmt" "sync" ) var balance int func Deposit(amount int) { b ...

  6. [日常] Go语言圣经-可变参数习题

    1.参数数量可变的函数称为为可变参数函数,例子就是fmt.Printf和类似函数2.参数列表的最后一个参数类型之前加上省略符号“...”3.虽然在可变参数函数内部,...int 型参数的行为看起来很像 ...

  7. [日常] Go语言圣经-Slice切片习题

    1.Slice(切片)代表变长的序列,序列中每个元素都有相同的类型,一个slice类型一般写作[]T,其中T代表slice中元素的类型:slice的语法和数组很像,只是没有固定长度而已,slice的底 ...

  8. [日常] Go语言圣经--接口约定习题2

    练习 7.3: 为在gopl.io/ch4/treesort (§4.4)的*tree类型实现一个String方法去展示tree类型的值序列. package main import( "f ...

  9. [日常] Go语言圣经-函数多返回值习题

    Go语言圣经-函数多返回值1.在Go中,一个函数可以返回多个值2.许多标准库中的函数返回2个值,一个是期望得到的返回值,另一个是函数出错时的错误信息3.如果一个函数将所有的返回值都显示的变量名,那么该 ...

随机推荐

  1. C#把汉字转换成16进制(HEX)并向串口发送数据

    报警器实例:(有发送,无返回获取) using System; using System.Collections.Generic; using System.Linq; using System.Te ...

  2. Android开发教程 - 使用Data Binding(四)在Fragment中的使用

    本系列目录 使用Data Binding(一)介绍 使用Data Binding(二)集成与配置 使用Data Binding(三)在Activity中的使用 使用Data Binding(四)在Fr ...

  3. [学习笔记]CDQ分治和整体二分

    序言 \(CDQ\) 分治和整体二分都是基于分治的思想,把复杂的问题拆分成许多可以简单求的解子问题.但是这两种算法必须离线处理,不能解决一些强制在线的题目.不过如果题目允许离线的话,这两种算法能把在线 ...

  4. Android实战源码--围住神经猫

    最终效果: AndroidManifest.xml <?xml version="1.0" encoding="utf-8"?> <manif ...

  5. python 多版本管理pyenv和virtualenv虚拟开发环境

    pyenv是管理多个python版本的工具. 1.pyenv的安装 git clone https://github.com/yyuu/pyenv.git ~/.pyenv 2.将PYENV_ROOT ...

  6. Windows平台下搭建自己的Git服务器

    该文章转自:http://www.codeceo.com/article/windows-git-server.html Gitblit 是一个纯 Java 库用来管理.查看和处理 Git 资料库,相 ...

  7. 【xsy2506】 bipartite 并查集+线段树

    题目大意:有$n$个点,你需要操作$m$次.每次操作为加入/删除一条边. 问你每次操作后,这$n$个点构成的图是否是二分图. 数据范围:$n,m≤10^5$. 此题并没有强制在线,考虑离线做法. 一条 ...

  8. Vue2.5开发去哪儿网App 第三章笔记 下

    1.样式的绑定 我们可以传给 v-bind:class 一个对象,以动态地切换 class   例如: :class="{activated:isactivated}" 上面的语法 ...

  9. Yii2+Swagger搭建RESTful风格的API项目

    在现有的Advanced Template上搭建RESTful API项目的步骤: 本案例前提说明: 本例中不使用\yii\rest\ActiveController自动创建的API,而是自定义一个A ...

  10. Android_EditText 打勾显示输入的密码 --EditText与setTransformationMethod

    实现目标: 实现原理: 为CheckBox添加一个监听器事件; 实现的源码: package edu.cquptzx.showPassword; import android.app.Activity ...