403错误表示服务器理解请求但拒绝执行,主因包括:一、服务器权限与配置限制;二、客户端请求特征异常;三、IP地址被网络层拦截;四、SSL/TLS协议不满足;五、应用层认证授权失败。

http.Get 能发请求,但默认行为常导致抓不到数据——不是协议问题,而是服务端拦截、编码错乱、Body 提前读取或 JS 渲染缺失。
为什么 http.Get 返回空内容或 403?
多数 HTTPS 网站会校验请求头,空 User-Agent 几乎必被拒。标准库不设默认 UA,http.DefaultClient 发出的请求在服务端日志里常显示为“bot”或直接 403。
- 必须显式设置
User-Agent:用&http.Client{Transport: &http.Transport{}}包裹,并在req.Header.Set("User-Agent", "...")中填值 - 部分站点还校验
Accept-Encoding、Referer,缺一可能返回空 HTML 或跳转到登录页 - 若目标页有重定向(如 HTTP → HTTPS、/ → /login),
http.Get默认跟随,但响应 Body 可能已被消耗,后续解析时读不到内容
中文乱码或 goquery.NewDocumentFromReader 解析失败
根本原因是网页声明的 charset(如 charset=gbk)与 Go 默认 UTF-8 解码不匹配,resp.Body 直接传给 goquery 会把字节当 UTF-8 解,结果全是 ???。
- 先用
golang.org/x/net/html/charset检测并转换编码:调用charset.NewReaderLabel(resp.Body, resp.Header.Get("Content-Type")) - 别直接传
resp.Body给NewDocumentFromReader,要包一层bufio.NewReader防止底层 buffer 不足导致解析中断 -
resp.StatusCode必须在读 Body 前检查,403/404 时Body可能非空但无有效 HTML,不判状态码就解析会白忙
目标数据在 JS 渲染后才出现,goquery 拿不到
右键“查看网页源代码”,搜关键词。如果搜不到,说明数据由 JS 动态注入——goquery 和 colly 都只处理初始 HTML,无法执行 JS。
立即学习“go语言免费学习笔记(深入)”;
- 优先查 Network 面板,找 XHR/Fetch 请求地址,用
http.Client直接调 API,比模拟浏览器快且稳定 - 真要渲染页面,用
chromedp,但它启动 Chrome 实例、内存占用高、部署需额外依赖,别为简单任务引入 -
colly的AllowURLRevisit和MaxDepth对 JS 渲染无效,开了也没用
并发抓取时连接失败或被限流
默认 http.DefaultClient 的 Transport 没设连接池上限和超时,10 个 goroutine 同时 Visit 可能瞬间打满文件描述符,触发 “too many open files” 或服务端返回 429。
- 必须配置
Transport.MaxIdleConns(建议 20)、MaxIdleConnsPerHost(建议 20)、IdleConnTimeout(建议 30s) - 每个请求都要设上下文超时:
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second),避免 DNS 卡住整个程序 - 用
colly时,并发数别一上来就设Parallelism: 10,从 2–3 起步,配合Delay: 1 * time.Second观察状态码变化
真正卡住人的从来不是 HTTPS 协议本身,而是服务端策略、字符集隐含规则、JS 渲染边界和并发资源控制——这些地方没对齐,http.Get 再成功也拿不到你要的数据。


















