fmt.Printlnlog.Println

保存在纯文本文件

纯文本文件是只保存文本了,不保存其格式设置的文件,最常见的如txt后缀文件、配置文件、源代码等等。。代码修改思路是

1. 修改parseUrls方法中打印的部分,改成写入文件:

func checkError(err error) {
    if err != nil {
        panic(err)
    }
}

_, err := f.WriteString(strings.Split(htmlquery.InnerText(url), "/")[4] + "\t" +
        htmlquery.InnerText(title) + "\n")
checkError(err)
复制代码

这样就把id和标题用制表符隔开,当然要注意最后还写入了换行符。每次调用WriteString写入文本后要判断是不是有错误err,这次抽象成了一个函数checkError,如果有错误说明有严重问题,这不是只打印信息说明文件就可以了,所以用panic直接抛错结束程序。

PS: 说一个细节,在Python中字符串拼接用+最好应该用join方法,但是在Golang中strings.Join是最慢的,而最快的是bytes.Buffer,具体的可以看延伸阅读链接2里面的实验。但是对于我们这种少量小文本拼接的需求就直接使用+,没有引入bytes.Buffer。

2. 修改main方法,初始化文件,并用defer在函数执行结束后关闭文件

func main() {
    start := time.Now()
    ch := make(chan bool)
    f, err := os.Create("movie.txt")
    checkError(err)
    defer f.Close()
    _, err = f.WriteString("ID\tTitle\n")
    checkError(err)

    for i := 0; i < 10; i++ {
        go parseUrls("https://movie.douban.com/top250?start="+strconv.Itoa(25*i), ch, f)
    }

    for i := 0; i < 10; i++ {
        <-ch
    }
    f.Sync()

    elapsed := time.Since(start)
    log.Printf("Took %s", elapsed)
}
复制代码
os.CreateID\tTitle\n

运行一下:

❯ go run doubanCrawler1.go
...
❯ wc -l movie.txt
251 movie.txt  # 一行字段描述,250行代表Top250个条目
❯ head -3 movie.txt
ID	Title
1292052	肖申克的救赎
1291546	霸王别姬
复制代码

保存在CSV文件

encoding/csv

先修改 parseUrls 方法中打印的部分,改成写入csv文件

import (
    ...
    "encoding/csv"
)

err := w.Write([]string{
    strings.Split(htmlquery.InnerText(url), "/")[4],
    htmlquery.InnerText(title)})
checkError(err)
复制代码

Write方法传入的是一个切片,元素分别是ID和标题。然后改main函数:

func main() {
    start := time.Now()
    ch := make(chan bool)
    f, err := os.Create("movie.csv")
    checkError(err)
    defer f.Close()

    writer := csv.NewWriter(f)
    defer writer.Flush()

    err = writer.Write([]string{"ID", "Title"})
    checkError(err)

    for i := 0; i < 10; i++ {
        go parseUrls("https://movie.douban.com/top250?start="+strconv.Itoa(25*i), ch, writer)
    }

    for i := 0; i < 10; i++ {
        <-ch
    }

    elapsed := time.Since(start)
    log.Printf("Took %s", elapsed)
}
复制代码
csv.NewWriter
❯ go run doubanCrawler2.go
...
❯ head -3 movie.csv
ID,Title
1295865,燃情岁月
1395091,未麻的部屋
复制代码

后记

虽然本节只是学习文件的写,没有读的内容。但是也算大体了解了文件操作。

代码地址

完整代码可以在这个地址找到。

延伸阅读