Colly 实战:3 分钟抓取 Hacker News 评论树
2025-07-14 17:57 更新
官方示例 50+ 行看得头大?我把它压缩成 20 行中文注释版,爬指定帖子的所有评论,自动递归成树形 JSON,浏览器直看!
一、整体思路(先背下来)
- 传帖子 ID → 访问
item?id=xxx
- 每条评论
<tr class="athing">
的40px
缩进就是层级 - 根据缩进宽度
/40
找到父节点,拼成树 - 输出漂亮 JSON
二、精简中文代码(20 行)
package main
import (
"encoding/json"
"flag"
"log"
"os"
"strconv"
"strings"
"github.com/gocolly/colly/v2"
)
// 单条评论
type Comment struct {
Author string `json:"作者"`
URL string `json:"链接"`
Comment string `json:"正文"`
Replies []*Comment `json:"回复"`
}
func main() {
// 1. 命令行参数:-id=38861503
id := flag.String("id", "", "Hacker News 帖子 ID")
flag.Parse()
if *id == "" {
log.Fatal("缺少 -id 参数,示例:-id=38861503")
}
c := colly.NewCollector()
var roots []*Comment
// 2. 解析每条评论
c.OnHTML(".comment-tree tr.athing", func(e *colly.HTMLElement) {
indent, _ := strconv.Atoi(e.ChildAttr("td.ind img", "width"))
depth := indent / 40 // 40px 一级
cmt := &Comment{Replies: []*Comment{}}
e.Unmarshal(cmt) // 自动填充 Author/URL/Comment
cmt.Comment = strings.TrimSpace(cmt.Comment)
// 3. 找到父节点并挂载
parent := roots
for i := 0; i < depth; i++ {
if len(parent) == 0 {
break
}
parent = parent[len(parent)-1].Replies
}
parent = append(parent, cmt)
})
// 4. 开始
c.Visit("https://news.ycombinator.com/item?id=" + *id)
// 5. 输出漂亮 JSON
enc := json.NewEncoder(os.Stdout)
enc.SetIndent("", " ")
_ = enc.Encode(roots)
}
三、3 步运行
步骤 | 命令 | 说明 |
---|---|---|
① 安装 | go mod init hn && go get github.com/gocolly/colly/v2 |
一键拉库 |
② 保存 | 复制代码 → main.go |
零配置 |
③ 爬取 | go run main.go -id=38861503 > result.json |
JSON 立即生成 |
四、结果预览(result.json)
[
{
"作者": "pg",
"链接": "item?id=38861503",
"正文": "This is the root comment...",
"回复": [
{
"作者": "user123",
"链接": "item?id=38861504",
"正文": "Good point!",
"回复": []
}
]
}
]
五、常见问题 30 秒排查
症状 | 原因 | 解决 |
---|---|---|
0 条评论 | 帖子 ID 错误/反爬 | 换热门帖子 + 加 UA |
层级错乱 | 缩进宽度改变 | 确认 40px 仍适用 |
中文乱码 | 终端编码 | 用 VS Code 打开 JSON |
六、1 分钟扩展
需求 | 改动 1 行 |
---|---|
存 CSV | 把 JSON 编码换成 csv.Writer |
存数据库 | OnHTML 里写 INSERT |
爬多帖 | 循环不同 -id 参数 |
以上内容是否对您有帮助:
更多建议: