Colly 实战:3 分钟爬完 Reddit 热帖
2025-07-14 18:24 更新
官方示例 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 |
以上内容是否对您有帮助:
更多建议: