Colly 请求上下文:让爬虫数据“随身携带”
2025-07-14 16:54 更新
想在请求之间传递自定义数据?用
Ctx.Put
/Ctx.Get
就像给每个请求发一张“身份证”,URL、标题、分类随用随取!
一、示例:
爬 编程狮课程频道,并携带课程分类:
package main
import (
"fmt"
"github.com/gocolly/colly/v2"
)
func main() {
c := colly.NewCollector()
// 1. 请求前把分类写进上下文
c.OnRequest(func(r *colly.Request) {
// 假设我们手动给不同课程加分类
r.Ctx.Put("category", "Go语言")
r.Ctx.Put("url", r.URL.String())
})
// 2. 响应后取出上下文里的数据
c.OnResponse(func(r *colly.Response) {
category := r.Ctx.Get("category")
url := r.Ctx.Get("url")
fmt.Printf("分类[%s] → 地址[%s] 已抓取 %d 字节\n",
category, url, len(r.Body))
})
// 3. 开始爬取
c.Visit("https://www.w3cschool.cn/go")
}
运行结果:
分类[Go语言] → 地址[https://www.w3cschool.cn/go] 已抓取 12345 字节
二、3 个典型使用场景
场景 | 存什么 | 代码示例 |
---|---|---|
列表 → 详情 | 课程名 | r.Ctx.Put("title", e.Text) |
分布统计 | 爬虫节点编号 | r.Ctx.Put("node", "worker-3") |
登录状态 | Token | r.Ctx.Put("jwt", token) |
三、进阶:多收集器共享上下文
列表收集器把数据传给详情收集器:
listC := colly.NewCollector()
detailC := colly.NewCollector()
// 列表收集器:拿到链接后附带标题
listC.OnHTML("a.course", func(e *colly.HTMLElement) {
ctx := colly.NewContext()
ctx.Put("title", e.Text)
detailC.Request("GET", e.Attr("href"), nil, ctx, nil)
})
// 详情收集器:读取标题
detailC.OnHTML("h1", func(e *colly.HTMLElement) {
title := e.Request.Ctx.Get("title")
fmt.Println("课程标题:", title)
})
四、常见坑 30 秒排查
坑 | 原因 | 解决 |
---|---|---|
取不到值 | 用错收集器 | 确保 Ctx.Put 和 Ctx.Get 在同一收集器或正确传递 |
并发冲突 | 多个 goroutine 写同一 key | 使用唯一 key 或加锁 |
内存泄露 | 大量数据塞 Ctx | 及时删除或用外部存储 |
五、1 分钟动手实验
- 打开 终端 → 新建
ctx.go
。 - 复制上方“中文注释”代码 → 运行。
- 观察终端:URL 和分类被一起打印,数据“随身携带”。
以上内容是否对您有帮助:
更多建议: