colly.NewCollector() 默认不处理重定向和 Cookie,导致 302 跳转静默失败、OnHTML 不触发;需手动启用重定向策略、CookieJar、并发限制(LimitRule)、编码转换及深度/大小限制。

colly.NewCollector() 初始化时为什么爬不到数据
默认情况下 colly.NewCollector() 不启用自动重定向和 Cookie 管理,遇到 302 跳转或需会话保持的站点(比如登录后页面)直接静默失败,控制台也没报错,看起来就像“没触发回调”。
- 加
c.AllowURLRevisit = true才能重复访问同一 URL(调试时常用) - 必须显式调用
c.WithTransport(&http.Transport{...})并设置RedirectPolicy,否则 301/302 就断了 - 需要 Cookie 支持?得传入带
http.CookieJar的 client,原生NewCollector()不带 - 常见错误现象:
OnHTML完全不执行,OnRequest有日志但响应体为空——大概率是跳转被吞了
OnHTML("a[href]") 提取链接总漏掉部分结果
OnHTML 是基于 GoQuery 的 CSS 选择器,它只处理当前响应体的 HTML 文档结构,不会自动解析 JS 渲染内容,也不递归进 iframe 或动态插入的 DOM。
- 目标链接在
<script>里拼接生成?OnHTML看不见,得用OnResponse配正则或json.RawMessage解析 API 返回 - 用了伪类如
a[href]:not([href^='javascript'])?colly 底层的 goquery 不支持大部分伪类,会静默忽略,换成OnXML或手动过滤更稳 - 多个相同 selector 的节点,但只处理第一个?检查是否误用了
Find().First().Attr(),应改用Each()遍历 - 注意编码:如果页面声明的是
gbk但 colly 按 utf-8 解,OnHTML可能完全匹配不上——得提前用SetResponseCallback转码
并发爬取时报 “too many open files” 或请求超时
colly 默认不限制并发,c.Limit(&colly.LimitRule{DomainGlob: "*", Parallelism: 2}) 必须手动设,否则瞬间发几百个连接,系统文件描述符耗尽,Linux 下直接报 socket: too many open files。
-
Parallelism建议从 2~5 开始调,不是越大越快;目标站反爬强的话,设成 1 更稳妥 - 别只设
LimitRule就完事,还要配c.MaxDepth = 2和c.MaxBodySize = 1 (1MB),防内存炸 - 超时控制得两头抓:
c.WithTransport里设Timeout、IdleConnTimeout,同时每个Request单独传colly.RequestTimeout(10 * time.Second) - 容易被忽略:DNS 缓存没开,高频请求下
net.Dial反复查 DNS,比网络慢还拖累——加&http.Transport{DialContext: ...}套用net.Resolver缓存
怎么让 colly 正确处理登录态和表单提交
colly 本身不模拟浏览器行为,所谓“登录”,本质是手动构造登录请求 + 持久化 Cookie + 后续请求复用该 client 实例。
立即学习“go语言免费学习笔记(深入)”;
- 先用
c.OnResponse捕获登录页的Set-Cookie,再确保后续请求走同一个Collector实例(CookieJar 是绑定在 http.Client 上的) - 表单 POST 别用
c.Post()直接发——它不走中间件链,OnRequest/OnResponse全失效;正确做法是c.Request("POST", url, bytes.NewReader(data), nil, nil) - CSRF token 怎么拿?在登录页的
OnHTML("input[name=csrf_token]")里提取,存到闭包变量或c.Context,再塞进 POST body - 注意 Referer:有些站校验来源,得在
Request的headers参数里手动加"Referer": "https://example.com/login"
最麻烦的从来不是语法,而是每个网站对 Cookie、Header、重定向、JS 渲染的组合策略都不一样——写死规则不如留好 OnResponse 日志开关,先看清真实流量再动手。


















