用Golang写爬虫(七) - 如何保存数据到文件

在以前的练习中得到的条目ID和标题直接用fmt.Println或者log.Println在终端打印出来了,可是在实际工做须要把它保存在文件或者数据库中。这篇文章学习一下保存到纯文本、CSV和JSON三种文件里。html

保存在纯文本文件

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

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直接抛错结束程序。github

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

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.Create建立一个文件,而后写了一行ID\tTitle\n描述字段。而在parseUrls函数中增长了参数f(类型是*os.File),这样就能够在parseUrls把抓到的数据写入文件了。最后还用了Sync方法,它的做用是将文件系统的最近写入的数据在内存中的拷贝刷新到硬盘中,这是一个安全保存数据的习惯。数据库

运行一下:安全

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

保存在CSV文件

数据处理工做中常常用到csv(逗号分隔值Comma-Separated Values)文件,其文件以纯文本形式存储表格数据(数字和文本),字段间用某种分隔符(常见逗号或制表符)分隔。Golang标准库中有用于编码csv文件的encoding/csv包,能够直接使用。仍是按以前的2步:bash

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

import (
    ...
    "encoding/csv"
)

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

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

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)
}
复制代码

首先仍是用os.Create建立一个文件,按习惯使用csv后缀。用csv.NewWriter建立一个写csv的writer。parseUrls的最后一个参数改为了writer(类型是*csv.Writer)。这样就能够了:学习

❯ go run doubanCrawler2.go
...
❯ head -3 movie.csv
ID,Title
1295865,燃情岁月
1395091,未麻的部屋
复制代码

后记

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

代码地址

原文地址: strconv.com/posts/save-…

完整代码能够在这个地址找到。

延伸阅读

  1. tutorialedge.net/golang/read…
  2. gocn.vip/question/26…
  3. golang.org/pkg/encodin…
相关文章
相关标签/搜索