Colly 多收集器:让爬虫分工协作

2025-07-11 15:21 更新

任务复杂时,把“一个工人”拆成“多个工人”——一个翻目录、一个拿详情,效率翻倍,代码更清爽。

一、为什么要用多个收集器?

想象你在爬 编程狮课程频道

任务 单收集器 多收集器
翻列表页 → 取 1000 门课程链接 逻辑混杂 列表收集器专职翻页
点进详情页 → 拿课程标题/价格 回调地狱 详情收集器专心解析
结果 代码臃肿、难调试 结构清晰、易维护

二、快速上手:3 步完成“分工”

1. 创建两个收集器

package main


import (
    "github.com/gocolly/colly/v2"
)


func main() {
    // ① 列表收集器:只负责翻页 + 提取详情页链接
    listC := colly.NewCollector(
        colly.AllowedDomains("www.w3cschool.cn"),
    )


    // ② 详情收集器:只负责解析课程详情
    detailC := colly.NewCollector(
        colly.AllowedDomains("www.w3cschool.cn"),
    )
}

2. 克隆收集器(配置共享)

如果两个收集器配置几乎一样,用 Clone() 一行搞定:

base := colly.NewCollector(
    colly.UserAgent("编程狮爬虫 1.0"),
    colly.AllowedDomains("w3cschool.cn"),
)
listC := base.Clone()   // 复用 UA 与域名白名单
detailC := base.Clone()

3. 传递上下文(共享数据)

列表页拿到课程 ID 后,传给详情收集器:

// 列表收集器:拿到链接 → 交给详情收集器
listC.OnHTML("a.course-card", func(e *colly.HTMLElement) {
    detailURL := e.Attr("href")
    // 把课程名放进上下文,后续直接取
    ctx := colly.NewContext()
    ctx.Put("courseName", e.Text)
    detailC.Request("GET", detailURL, nil, ctx, nil)
})


// 详情收集器:用上下文里的数据
detailC.OnHTML("h1", func(e *colly.HTMLElement) {
    courseName := e.Request.Ctx.Get("courseName")
    println("课程名:", courseName, " 标题:", e.Text)
})

三、完整示例:爬“编程狮课程”

package main


import (
    "github.com/gocolly/colly/v2"
)


func main() {
    // 公共配置
    base := colly.NewCollector(
        colly.UserAgent("编程狮-多收集器-Demo"),
        colly.AllowedDomains("www.w3cschool.cn"),
    )


    listC := base.Clone()
    detailC := base.Clone()


    // 列表页:翻页 + 发链接
    listC.OnHTML("a.course-item", func(e *colly.HTMLElement) {
        ctx := colly.NewContext()
        ctx.Put("courseName", e.Text)
        detailC.Request("GET", e.Attr("href"), nil, ctx, nil)
    })


    // 详情页:解析
    detailC.OnHTML("h1", func(e *colly.HTMLElement) {
        courseName := e.Request.Ctx.Get("courseName")
        println("抓到课程:", courseName)
    })


    // 从第一页开始
    listC.Visit("https://www.w3cschool.cn/course")
}

运行结果(示意):

抓到课程:Go 入门教程
抓到课程:Python 爬虫实战
...

四、调试小技巧:一眼看出哪个收集器

在日志里加 collector.ID

listC.OnRequest(func(r *colly.Request) {
    println("[列表收集器]", r.URL)
})
detailC.OnRequest(func(r *colly.Request) {
    println("[详情收集器]", r.URL)
})

五、实战选型速查表

场景 推荐做法
列表 + 详情 两个收集器 + Clone()
不同域名/UA 独立 NewCollector
需要上下文 Request(..., ctx)

六、1 分钟动手实验

  1. 打开 Go 环境 → 新建文件。
  2. 复制“完整示例” → 把域名换成你正在学的站点 → 运行。
  3. 观察终端:列表、详情日志是否交替出现。
以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号