go反爬核心是构造合规请求包而非模拟人,关键在user-agent/referer组合、sec-ch-ua补全、禁用http/2、定制tls指纹、独立cookiejar及按域名限流。

GoLand 本身不参与反爬逻辑,它只是写代码的工具;真正起作用的是你写的 http.Client 配置、header 组合、TLS 行为和 Cookie 管理方式。别在 IDE 设置里找“反爬开关”,重点是把请求层该关的关掉、该补的补全、该隔离的隔离。
为什么不能共用一个 http.Client 实例打多个域名
不同网站对 TLS 握手扩展、HTTP 版本、Cookie 域策略容忍度差异极大。比如 A 站接受 Sec-Ch-Ua,B 站却因识别出非浏览器 TLS 扩展直接返回 403;C 站依赖 Set-Cookie: Secure,而你的 transport 没走 TLS,cookie 就被静默丢弃。
- 每个目标域名配独立
http.Client,Transport单独初始化 - 显式禁用 HTTP/2:
ForceAttemptHTTP2: false - 替换原生 TLS 实现,用
github.com/zmap/zcrypto/tls或github.com/senghoo/golang-fingerprint注入浏览器指纹 - UA 和 Referer 必须动态生成:UA 从预定义 slice 随机取,Referer 严格设为上一级页面 URL(如抓
/news/123前,先 GET/news/,再把该响应 URL 设为 Referer)
CookieJar 失效的三个隐蔽原因
看似设置了 cookiejar.New(nil),但 cookie 实际没生效,常见于:
- 标准
net/http/cookiejar不支持 Domain 字段宽松匹配(如Set-Cookie: domain=.example.com被当成无效 domain),导致 cookie 存不进 jar -
SameSite=Strict或Secure的 cookie 在非 HTTPS 请求中被拒绝,而你的 transport 没启用 TLS,却还在发 HTTP 请求 - 多个 goroutine 并发写同一个 jar,发生竞争丢失
正确做法是用 colly.CookieJar(它基于标准库但做了 Domain/path 修正),首次访问前手动注入可信 Cookie(比如从浏览器导出的 cf_clearance),调用 c.SetCookies(url, cookies)。
限流不是 time.Sleep,而是按域名独立控制
单纯 time.Sleep 只控制发起间隔,但真实瓶颈常在 DNS 解析、TLS 握手、服务端排队——你 sleep 了 2 秒,实际请求间隔可能是 8 秒,反而触发“低频慢速攻击”检测。
- 用
golang.org/x/time/rate.Limiter,但必须为每个域名建独立实例(map[string]*rate.Limiter) - 避免全局共享 limiter,否则 a.example.com 的限流会拖慢 b.example.com
- 遇到
429或503主动退避,用指数退避重试(time.AfterFunc+ 递增 delay) - 监控响应头里的
CF-RAY、X-RateLimit-Remaining等信号,动态调优 limiter 参数
最容易被忽略的是 TLS 指纹和 Cookie 域匹配逻辑——这两个点不修,其他都白搭。WAF 层一眼就能看出你用的是 Go 默认 crypto/tls,或者 cookie 明明设了 domain=.site.com 却没存进 jar,这种低级信号比 UA 假不假更致命。











