colly 的 onhtml 拿不到标题,主因是网页无静态 标签(如 spa 页面)、响应未加载完即解析、未处理 js 渲染内容、编码未设 utf-8 或选择器未覆盖 og:title 等元标签。

为什么 Colly 的 OnHTML 拿不到标题?
常见现象是写了 OnHTML("title", ...) 却始终没触发回调,或者返回空字符串。根本原因不是选择器写错了,而是网页可能没用 <title></title> 标签(比如 SPA 页面靠 JS 渲染),或者响应体根本没加载完就被解析了。
- 先确认目标页是否真有静态
<title></title>:用浏览器“查看页面源代码”(不是开发者工具的 Elements 面板),搜<title></title> - Colly 默认不执行 JS,所以 React/Vue 项目里
document.title动态设置的内容完全不可见 - 如果页面用了
<meta property="og:title">,得单独写OnHTML("meta[property='og:title']", ...) - 注意 HTML 解析依赖字符编码,中文标题乱码常因响应头没声明
charset=utf-8,可在c.OnResponse里手动调用resp.Body.SetCharset("utf-8")
如何用 colly.NewCollector 控制并发和重试
默认配置下,Colly 会并发请求、自动重试失败链接,但没设限——爬几个页面就可能被封 IP 或触发反爬。
- 限制并发数:传入
colly.Async(true)+colly.MaxDepth(2)+colly.MaxBodySize(1024 * 1024)防止下载大文件 - 重试逻辑要自己加:Colly 不内置 HTTP 状态码重试,需在
OnError里判断err.Error()是否含"timeout"或"connection refused",再调用c.Visit(req.URL.String()) - 加随机延迟:在
OnRequest回调里用time.Sleep(time.Second * time.Duration(rand.Intn(2)+1)),避免请求频率过高 - 别忽略 User-Agent:不设
c.UserAgent = "Mozilla/5.0 ...",很多站直接返回 403
c.OnHTML 提取文本时,为什么 e.Text 是空的?
这是新手最常卡住的地方:e.Text 只返回元素**直接子节点的文本内容**,不递归抓取所有后代文本,也不处理换行缩进。
- 例如
<h1> <span>Hello</span> World</h1>中,e.Text返回" World"(只取 span 后面的纯文本) - 要拿完整文本,改用
e.DOM.Text()(需 import"github.com/PuerkitoBio/goquery"),它等价于 jQuery 的.text() - 如果目标是
<title>Go 语言入门 - 教程网</title>,直接e.Text就够用;但如果是嵌套结构或带注释的标题,必须切到 DOM 层 - 注意空格和换行:
e.Text会保留原始空白,建议结尾加strings.TrimSpace()
采集结果怎么安全存成 JSON 而不丢数据?
直接 json.Marshal 结构体容易 panic,尤其字段含 nil 指针、未导出字段或非 JSON 可序列化类型(比如 *goquery.Selection)。
立即学习“go语言免费学习笔记(深入)”;
- 定义结果结构体时,所有字段必须首字母大写(导出),且加
json:"title"tag 显式控制 key 名 - 不要把
*colly.Response或*goquery.Selection存进结构体——它们不是纯数据,提取后立刻转成string或int - 写文件前检查
os.IsNotExist(err),避免路径不存在导致静默失败;用os.WriteFile(filename, data, 0644)替代os.Create+Write组合 - 如果并发采集多个页面,别用全局 map 存结果——竞态风险高,改用
sync.Map或 channel 收集后再统一序列化
真正麻烦的从来不是写几行 OnHTML,而是搞清目标页面的真实结构、HTTP 响应的编码细节、以及 Go 里值和指针在序列化时的隐式行为。










