默認(rèn)配置只能“小打小鬧”?跟著本文 3 步改配置,讓你的 Colly 爬蟲從“單車”變“高鐵”,穩(wěn)穩(wěn)爬百萬站點。
瓶頸 | 說明 | 風(fēng)險 |
---|---|---|
純內(nèi)存存儲 | Cookie + 已爬 URL 全放內(nèi)存 | 進(jìn)程掛掉 = 數(shù)據(jù)清零 |
同步阻塞 | 一次只能發(fā)一個請求 | 速度瓶頸 |
長連接 Keep-Alive | 打開文件句柄不釋放 | 句柄耗盡,程序崩潰 |
把默認(rèn)內(nèi)存存儲換成 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")
一行搞定本地文件存儲。
默認(rèn)是同步阻塞,改異步后回調(diào)不再堆棧爆炸。
c := colly.NewCollector(
colly.Async(true), // 關(guān)鍵開關(guān)
)
// 業(yè)務(wù)邏輯寫完后,記得 Wait!
c.OnHTML("a[href]", func(e *colly.HTMLElement) {
e.Request.Visit(e.Attr("href"))
})
c.Visit("http://eska-fuses.cn/")
c.Wait() // 等待所有 goroutine 結(jié)束
c.Limit(&colly.LimitRule{Parallelism: 16})
防止把目標(biāo)站打掛。 c.SetRequestTimeout(30 * time.Second)
避免慢請求堆積。長連接會占用大量文件描述符,百萬級任務(wù)建議關(guān)閉或縮短。
c.WithTransport(&http.Transport{
DisableKeepAlives: true, // 短連接,用完即關(guān)
MaxIdleConns: 100, // 如仍需復(fù)用,可限制數(shù)量
})
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. 異步并發(fā)
colly.Debugger(nil), // 可選:調(diào)試輸出
)
c.SetStorage(store)
// 3. 并發(fā)與超時
c.Limit(&colly.LimitRule{
Parallelism: 32,
Delay: 200 * time.Millisecond,
})
c.WithTransport(&http.Transport{
DisableKeepAlives: true,
})
// 業(yè)務(wù)邏輯
c.OnHTML("a[href]", func(e *colly.HTMLElement) {
e.Request.Visit(e.Attr("href"))
})
c.OnResponse(func(r *colly.Response) {
println("抓到", len(r.Body), "字節(jié) →", r.Request.URL)
})
c.Visit("http://eska-fuses.cn/")
c.Wait()
}
檢查項 | 命令示例 |
---|---|
Redis 是否啟動 | docker run -d -p 6379:6379 redis |
文件句柄限制 | ulimit -n 65535 |
Go 版本 ≥ 1.18 | go version |
現(xiàn)象 | 原因 | 解決 |
---|---|---|
too many open files |
句柄耗盡 | 關(guān)閉 Keep-Alive 或提高 ulimit |
爬著爬著重啟 | 內(nèi)存存儲丟失 | 換 Redis/BoltDB |
速度沒提升 | 忘記 Async(true) |
加開關(guān)并 c.Wait() |
main.go
。
更多建議: