用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…
相關文章
相關標籤/搜索