返回403或空白因未设User-Agent被网站拒绝,且net/http无法处理JS渲染、Cloudflare防护等动态内容。

用 net/http 发起请求时,为什么返回空或 403?
不是所有网站都欢迎爬虫,http.DefaultClient 默认不带 User-Agent,很多站点直接拒掉。更麻烦的是,有些页面依赖 JavaScript 渲染,net/http 拿到的只是原始 HTML 骨架,根本没数据。
- 务必设置
req.Header.Set("User-Agent", "Mozilla/5.0..."),否则多数新闻、电商站会返回 403 或空白响应 - 遇到动态加载内容(比如滚动加载的列表),
net/http无能为力,得换方案,别硬扛 - 如果目标站用了 Cloudflare 或验证码防护,
net/http加上 UA 也没用,这时候该停手,别浪费时间写重试逻辑
解析 HTML 用 golang.org/x/net/html 还是第三方库?
golang.org/x/net/html 是官方维护的解析器,轻量、无依赖、内存友好,适合结构清晰、静态的页面;但它不支持 CSS 选择器,写起来像在遍历 DOM 树,容易出错。
- 简单页面(如政府公示页、博客文章列表)直接用
html.Parse()+ 递归查找Node就够了 - 需要写
div.post > h2.title这种表达式?上github.com/PuerkitoBio/goquery,它包装了官方 parser,语法接近 jQuery - 注意:goquery 不自动处理编码,遇到 GBK 页面要先用
golang.org/x/text/encoding转 UTF-8,否则中文全乱码
并发抓取多个 URL 时,为什么程序卡死或被封 IP?
开 100 个 goroutine 同时请求,看似快,实则触发两个问题:DNS 解析阻塞 + 目标站限流。Go 的 http.Transport 默认只允许 100 个空闲连接,但更重要的是,没有节制的并发等于主动找封。
- 用
semaphore控制并发数,比如限制 5–10 个 goroutine 同时发请求,比盲目堆数量更稳 - 给每个请求加随机延时(
time.Sleep(time.Second * 1 + rand.Int63n(2e9))),避免请求扎堆 - 复用
http.Client和http.Transport,别每次请求都 new 一个 client,否则 DNS 缓存失效、连接池白搭
保存结果到文件时,os.OpenFile 的 flag 参数怎么选?
爬虫跑一晚上,结果全写进一个文件,中途出错就前功尽弃。很多人用 os.O_CREATE | os.O_WRONLY 从头覆盖,结果调试时反复运行,上一轮数据没了。
立即学习“go语言免费学习笔记(深入)”;
- 追加写入用
os.O_CREATE | os.O_WRONLY | os.O_APPEND,安全又省事 - 想按天分文件?构造路径如
fmt.Sprintf("data_%s.json", time.Now().Format("2006-01-02")),别硬编码文件名 - 写 JSON 到文件时,别用
json.MarshalIndent带缩进——体积翻倍、IO 更慢,生产环境用json.Marshal就行
真正难的从来不是怎么发请求、怎么解析,而是判断这个页面值不值得爬、要不要等、要不要降级、数据要不要校验。这些没法靠库解决,得看日志、看响应头、看网络波动,然后手动调参数。


















