首页
/
Go-Colly 中文教程
/
Colly 实战:3 分钟爬完 Reddit 热帖
Colly 实战:3 分钟爬完 Reddit 热帖
官方示例 40 行不够直观?我把它压缩成 20 行中文注释版 ,支持 任意子版块 、自动翻页 、限速防封 ,直接输出 JSON!
一、整体思路(先背下来)
入口 :r/programming/hot
解析每条帖子 :标题、链接、评论数
自动下一页 :.next-button
限速 :并发 2 + 随机 5 秒延迟
二、精简中文代码(20 行)
package main
import (
"encoding/json"
"flag"
"fmt"
"time"
"github.com/gocolly/colly/v2"
)
// 帖子结构体
type Post struct {
Title string `json:"标题"`
Link string `json:"链接"`
Comments string `json:"评论链接"`
Crawled time.Time `json:"抓取时间"`
}
func main() {
// 1. 命令行参数:-sub=programming
sub := flag.String("sub", "programming", "子版块名称")
flag.Parse()
var posts []Post
c := colly.NewCollector(
colly.AllowedDomains("www.reddit.com"),
colly.Async(true),
)
// 2. 解析帖子
c.OnHTML(".top-matter", func(e *colly.HTMLElement) {
posts = append(posts, Post{
Title: e.ChildText("a[data-event-action=title]"),
Link: e.ChildAttr("a[data-event-action=title]", "href"),
Comments: e.ChildAttr("a[data-event-action=comments]", "href"),
Crawled: time.Now(),
})
})
// 3. 自动翻页
c.OnHTML("span.next-button", func(e *colly.HTMLElement) {
e.Request.Visit(e.ChildAttr("a", "href"))
})
// 4. 限速防封
c.Limit(&colly.LimitRule{
Parallelism: 2,
RandomDelay: 5 * time.Second,
})
// 5. 启动
startURL := fmt.Sprintf("https://www.reddit.com/r/%s/hot/", *sub)
c.Visit(startURL)
c.Wait()
// 6. 输出 JSON
data, _ := json.MarshalIndent(posts, "", " ")
fmt.Println(string(data))
}
三、3 步跑通
步骤
命令/操作
说明
① 安装
go mod init reddit && go get github.com/gocolly/colly/v2
一键拉库
② 保存
复制上方代码 → main.go
零配置
③ 运行
go run main.go -sub=programming > posts.json
生成 JSON
四、结果示例(posts.json)
[
{
"标题": "Show HN: A tiny tool written in Go to ...",
"链接": "https://github.com/...",
"评论链接": "https://www.reddit.com/r/programming/comments/...",
"抓取时间": "2024-07-14T12:34:56Z"
}
// ...更多帖子
]
五、常见问题速查
症状
原因
解决
0 条数据
反爬 / 改版
加 User-Agent 或更新选择器
403 错误
限速
调大 RandomDelay 或降 Parallelism
下一页失效
新版 Reddit
把选择器换成 a[rel="nofollow next"]
六、1 分钟扩展
需求
改动 1 行
爬多个版块
go run main.go -sub=golang,python
存 CSV
把 JSON 编码换成 csv.Writer
存数据库
在 OnHTML 里写 INSERT