比Python还快?Go也有属于自己的爬虫
新手教程:Go 语言实现DoubanTop 250 数据爬取及保存到 CSV 和 Excel
在本教程中,我们将会详细讲解如何通过 Go 语言和 Colly 爬虫框架,爬取豆瓣电影 Top 250 的数据,并将结果分别保存到 CSV 和 Excel 文件中。通过这个项目,你可以学习如何使用 Go 进行网络爬虫,并把数据格式化保存下来。
技术栈
- 编程语言:Go
- 网络爬虫框架:Colly
- 数据保存格式:CSV 和 Excel
第一步:项目初始化
首先,我们需要在项目根目录下初始化 Go 模块。你可以通过以下命令完成:
go mod init "<项目仓库名>"
这个命令会生成一个 go.mod
文件,用于管理项目的依赖。
第二步:创建项目结构
-
创建
main.go
文件在项目根目录下创建一个
main.go
文件,这是整个程序的入口文件,包含主程序逻辑。 -
创建
output
文件夹为了存储输出的文件,我们在项目根目录下创建一个
output
文件夹,并在这个目录内创建两个文件:CSV.go
和EXCEL.go
。这两个文件分别用来保存爬取到的数据到 CSV 和 Excel 文件。 -
项目目录结构
├── main.go ├── output/ │ ├── CSV.go │ └── EXCEL.go └── go.mod
第三步:安装依赖
-
安装 Colly 框架
Colly 是一个强大的 Go 语言爬虫框架,可以轻松地从网页中提取数据。通过下面的命令安装 Colly:
go get -u github.com/gocolly/colly/v2
-
安装进度条依赖
为了让爬取过程更加直观,我们将使用
progressbar
包来显示爬取进度:go get -u github.com/schollz/progressbar/v3
-
安装 Excel 操作依赖
为了将数据导出到 Excel 文件,我们需要使用
excelize
包:go get -u github.com/xuri/excelize/v2
第四步:编写 CSV.go 文件
在 output/CSV.go
中,我们编写保存 CSV 文件的逻辑。该文件的作用是接受一个数据数组,并将其保存为 CSV 格式。
package utils
import (
"encoding/csv"
"os"
)
// SaveToCSV 将数据保存到 CSV 文件
func SaveToCSV(filename string, data [][]string) error {
file, err := os.Create(filename)
if err != nil {
return err
}
defer file.Close()
writer := csv.NewWriter(file)
defer writer.Flush()
// 写入表头
header := []string{"标题", "类型", "评价"}
if err := writer.Write(header); err != nil {
return err
}
// 写入数据
for _, record := range data {
if err := writer.Write(record); err != nil {
return err
}
}
return nil
}
第五步:编写 EXCEL.go 文件
在 output/EXCEL.go
中,我们编写保存 Excel 文件的逻辑。这里使用 excelize
库来生成 Excel 文件。
package utils
import (
excelize "github.com/xuri/excelize/v2"
)
// SaveToExcel 将数据保存到 Excel 文件
func SaveToExcel(filename string, data [][]string) error {
f := excelize.NewFile()
sheetName := "Sheet1"
// 添加表头
header := []string{"标题", "类型", "评价"}
data = append([][]string{header}, data...)
// 创建新的工作表
index, err := f.NewSheet(sheetName)
if err != nil {
return err
}
// 写入数据
for i, row := range data {
for j, cell := range row {
cellName, _ := excelize.CoordinatesToCellName(j+1, i+1)
f.SetCellValue(sheetName, cellName, cell)
}
}
f.SetActiveSheet(index)
return f.SaveAs(filename)
}
第六步:编写 Main.go 文件
在 main.go
文件中编写爬虫的核心逻辑,并调用 CSV.go
和 EXCEL.go
中的保存函数。
package main
import (
"os"
"fmt"
"strings"
"time"
"douban_250/utils"
"github.com/gocolly/colly/v2"
"github.com/gocolly/colly/v2/extensions"
"github.com/schollz/progressbar/v3"
)
func main() {
var data [][]string
startTime := time.Now() // 记录开始时间
// 创建一个新的 Colly 爬虫实例
c := colly.NewCollector(
colly.IgnoreRobotsTxt(), // 忽略 robots.txt 文件
colly.MaxDepth(2), // 设置爬取的最大深度为 2
colly.AllowedDomains("movie.douban.com", "sec.douban.com"), // 设置允许访问的域名
)
extensions.RandomUserAgent(c) // 设置随机 User-Agent
c.OnHTML("#content > div > div.article > ol > li", func(e *colly.HTMLElement) {
// 提取标题
title := e.ChildText(".hd .title:first-child")
// 提取完整文本
fullText := e.ChildText(".bd p")
// 从 `fullText` 中提取 `类型` 部分
lines := strings.Split(fullText, "\n")
var typeLine string
if len(lines) > 1 {
typeLine = strings.TrimSpace(lines[1])
// 去掉多余的空白字符
typeLine = strings.ReplaceAll(typeLine, " ", " ")
typeLine = strings.TrimSpace(typeLine)
}
// 提取评价
quote := e.ChildText(".quote .inq")
// 输出结果
// fmt.Printf("标题: %s\n", title)
// fmt.Printf("类型: %s\n", typeLine)
// fmt.Printf("评价: %s\n", quote)
// 保存数据到切片
data = append(data, []string{title, typeLine, quote})
})
// 请求之前的回调函数
c.OnRequest(func(r *colly.Request) {
fmt.Println("正在访问:", r.URL.String())
})
// 请求之后的回调函数
c.OnResponse(func(r *colly.Response) {
// 检查是否重定向
if r.StatusCode == 302 {
fmt.Println("重定向到:", r.Headers.Get("Location"))
} else if r.StatusCode == 403 {
// 检查响应内容和域名
body := string(r.Body)
if strings.Contains(body, "Forbidden") || strings.Contains(body, "403") {
if strings.Contains(r.Request.URL.String(), "sec.douban.com") {
fmt.Println("403 Forbidden: IP 被封禁或需要验证")
} else {
fmt.Println("403 Forbidden: 访问受限")
}
} else {
fmt.Println("响应状态码:", r.StatusCode)
}
} else {
fmt.Println("响应状态码:", r.StatusCode)
}
})
// 设置进度条, 爬取前 10 页
totalPages := 10 // 总共只有10页,即250条数据
bar := progressbar.Default(int64(totalPages), "爬取进度条")
// 爬取分页内容
for i := 0; i <= totalPages; i++ {
// 构造分页 URL
pageURL := fmt.Sprintf("https://movie.douban.com/top250?start=%d&filter=", i*25)
err := c.Visit(pageURL)
if err != nil {
fmt.Println("页面访问失败:", err)
}
fmt.Println("第", i+1, "页爬取完成")
bar.Add(1) // 更新进度条
}
// 保存到 CSV 文件
err := utils.SaveToCSV("movies.csv", data)
if err != nil {
fmt.Println("保存到 CSV 文件失败:", err)
}
// 保存到 Excel 文件
err = utils.SaveToExcel("movies.xlsx", data)
if err != nil {
fmt.Println("保存到 Excel 文件失败:", err)
}
// 计算总耗时
elapsedTime := time.Since(startTime)
fmt.Printf("总耗时: %s\n", elapsedTime)
// 提示用户按任意键退出
fmt.Println("请按任意键退出...")
_, _ = os.Stdin.Read(make([]byte, 1)) // 等待用户输入
}
第七步:运行程序
在项目根目录下运行以下命令来启动爬虫程序:
go run main.go
程序会自动开始爬取豆瓣电影 Top 250 的数据,并将结果分别保存到 movies.csv
和 movies.xlsx
文件中。
结语
通过本教程,你已经掌握了使用 Go 语言和 Colly 框架构建网络爬虫的基本方法,并了解了如何将数据保存到 CSV 和 Excel 文件。你可以根据自己的需求,进一步扩展此爬虫功能,比如抓取更多信息,处理验证码,或者实现更加复杂的爬取逻辑。
- 感谢你赐予我前进的力量