Colly 高并发爬取:百万级站点轻松拿捏

2025-07-11 17:46 更新

默认配置只能“小打小闹”?跟着本文 3 步改配置,让你的 Colly 爬虫从“单车”变“高铁”,稳稳爬百万站点。

一、默认配置的 3 个瓶颈

瓶颈 说明 风险
纯内存存储 Cookie + 已爬 URL 全放内存 进程挂掉 = 数据清零
同步阻塞 一次只能发一个请求 速度瓶颈
长连接 Keep-Alive 打开文件句柄不释放 句柄耗尽,程序崩溃

二、3 步优化:代码级“一键升级”

1️⃣ 换持久化存储:断电也不怕

把默认内存存储换成 Redis(或 BoltDB/SQLite 等),已爬 URL 实时落盘。

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


func main() {
    store, _ := redisstorage.New(
        &redisstorage.Options{Address: "127.0.0.1:6379"},
    )
    c := colly.NewCollector()
    c.SetStorage(store) // 完成“搬家”
}

小贴士:没有 Redis?用 boltdb.New("crawler.db") 一行搞定本地文件存储。

2️⃣ 开启异步:并发飞起

默认是同步阻塞,改异步后回调不再堆栈爆炸。

c := colly.NewCollector(
    colly.Async(true), // 关键开关
)


// 业务逻辑写完后,记得 Wait!
c.OnHTML("a[href]", func(e *colly.HTMLElement) {
    e.Request.Visit(e.Attr("href"))
})


c.Visit("https://www.w3cschool.cn/")
c.Wait() // 等待所有 goroutine 结束

  • 并发数控制:加 c.Limit(&colly.LimitRule{Parallelism: 16}) 防止把目标站打挂。
  • 内存保护c.SetRequestTimeout(30 * time.Second) 避免慢请求堆积。

3️⃣ 关闭 Keep-Alive:句柄不再爆表

长连接会占用大量文件描述符,百万级任务建议关闭或缩短。

c.WithTransport(&http.Transport{
    DisableKeepAlives: true, // 短连接,用完即关
    MaxIdleConns:        100, // 如仍需复用,可限制数量
})

三、完整示例:一键启动“高铁模式”

package main


import (
    "time"
    "github.com/gocolly/colly/v2"
    "github.com/gocolly/colly/v2/storage/redisstorage"
)


func main() {
    // 1. 持久化存储
    store, _ := redisstorage.New(
        &redisstorage.Options{Address: "127.0.0.1:6379"},
    )


    c := colly.NewCollector(
        colly.Async(true),               // 2. 异步并发
        colly.Debugger(nil),             // 可选:调试输出
    )
    c.SetStorage(store)


    // 3. 并发与超时
    c.Limit(&colly.LimitRule{
        Parallelism: 32,
        Delay:       200 * time.Millisecond,
    })
    c.WithTransport(&http.Transport{
        DisableKeepAlives: true,
    })


    // 业务逻辑
    c.OnHTML("a[href]", func(e *colly.HTMLElement) {
        e.Request.Visit(e.Attr("href"))
    })
    c.OnResponse(func(r *colly.Response) {
        println("抓到", len(r.Body), "字节 →", r.Request.URL)
    })


    c.Visit("https://www.w3cschool.cn/")
    c.Wait()
}

四、运行前检查清单

检查项 命令示例
Redis 是否启动 docker run -d -p 6379:6379 redis
文件句柄限制 ulimit -n 65535
Go 版本 ≥ 1.18 go version

五、常见问题速查

现象 原因 解决
too many open files 句柄耗尽 关闭 Keep-Alive 或提高 ulimit
爬着爬着重启 内存存储丢失 换 Redis/BoltDB
速度没提升 忘记 Async(true) 加开关并 c.Wait()

六、1 分钟实验

  1. 打开 终端 → 新建 main.go
  2. 复制“完整示例” → 本地或在线 Redis 一键启动。
  3. 观察终端:并发 32 路输出,速度肉眼可见提升!
以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号