社交爬虫 User-Agent 真相表:按 UA 分叉内容的代价
你在 Chrome 打开线上页:新主视觉、正确的 og:title、新的 og:image。市场同事把同一 URL 丢进 Slack,卡片仍是上季度活动图和 A/B「对照组」模板里的标题。
不是标签被半夜改坏了,而是两个不同的 User-Agent 打到同一路径,拿到了两份不同的 HTML。机器人那条链路还在旧 CMS 布局;人类已经看到了改版。
这篇只谈这件事:社交爬虫自称是谁、会不会跑 JS、怎么用 curl 自证,以及按 UA 分叉内容什么时候是修复、什么时候是事故。
同一 URL,两个世界
机器人与浏览器分叉的常见机制:
| 机制 | 爬虫拿到的 | 你在浏览器里看到的 |
|---|---|---|
| SSR / SPA 壳 | 初始 HTML 里 meta 空或占位 | hydration 之后才有标签 |
| A/B 或个性化 | 对照 / 默认变体 | 胜出变体或登录态体验 |
| Bot 对抗 / 挑战页 | 403、验证页或极简挑战 HTML | 过 JS / cookie 后的完整页 |
| CDN / WAF 规则 | 对已知 bot UA 的另一缓存键或拦截 | 浏览器边的热缓存 |
| 故意的「bot HTML」 | 只服务分享的精简 markup | 完整营销页 |
前四类经常被误诊成「Open Graph 坏了」。第五类可以合理(不必为爬虫吐 2MB SPA 壳),但活动结束后若只改人类模板、忘了 bot 模板,就会变成事故。
安全先讲清楚:不要把「敏感信息只放在非 bot 分支」当成安全措施。 爬虫和攻击者都能自己选 User-Agent。只对浏览器暴露的内容,对任何会改 UA 的人仍然是公开的。
User-Agent 真相表
下表来自 OGKit 的平台档案(@og-kit/core)。每一行都带来源与核实日期。没有可靠数字的地方写 未知 / unverified——不编造 TTL。
| 平台 | User-Agent(代表性) | 执行 JS? | 分享缓存 TTL | 刷新路径 | 来源 · 核实 |
|---|---|---|---|---|---|
| Facebook / Meta | facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php) |
否 | 未知 | Sharing Debugger 重新抓取 | 官方 · 2026-07-01 |
| X (Twitter) | Twitterbot/1.0 |
否 | 常被引用约 7 天(非官方固定值) | Card Validator / 改 URL 后重分享 | UA 官方;TTL 社区 · 2026-07-01 |
LinkedInBot/1.0 (compatible; Mozilla/5.0; Apache-HttpClient +http://www.linkedin.com) |
否 | 约 7 天(社区) | Post Inspector | 社区 · 2026-07-01 | |
| Slack | Slackbot-LinkExpanding 1.0 (+https://api.slack.com/robots) |
否 | 未知 | 重新分享(无公开 debugger) | UA 官方 · 2026-07-01 |
| Discord | Mozilla/5.0 (compatible; Discordbot/2.0; +https://discordapp.com) |
否 | 未知 | 改 query 或 embed 工具 | 社区 · 2026-07-01 |
WhatsApp/2.0(存在变体;常复用 Meta 爬虫基础设施) |
否 | 未知 | 无公开 debugger;等待或改 URL | 社区 · 2026-07-01 | |
| Telegram | TelegramBot (like TwitterBot) |
否 | 未知 | @WebpageBot 或重分享 |
社区 · 2026-07-01 |
| Googlebot(对照) | Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html) |
是(渲染服务) | 与 OG 卡无关 | Search Console URL 检查 | 官方 · 2026-07-01 |
字段级细节(图片字节预算、截断、字段优先级)在线上的平台档案页——同一数据源,带出处徽章。
怎么读这张表
- 社交 OG 爬虫不跑你的 JavaScript。 若
og:*只在 hydration 后出现,卡片就是空的。所以才会有「DevTools 里正常、LinkedIn 上没有」。相关规则:og-tags-require-javascript。 - Google 不是社交预览爬虫。 只为 Googlebot 优化、或只在浏览器里自测,不能证明 Slack 或 Meta 看到同一份 HTML。
- TTL 列不是 SLA。 来源是
community或unverified时,只当规划参考。改标签或换图后,走各平台官方 rescrape(rescrape 助手),不要干等传闻中的过期时间。
自己验证(curl -A)
若中间件按 UA 分流,不要只信浏览器「查看源代码」。按机器人身份抓:
URL="https://example.com/launch"
# 基线(通用浏览器向 UA)
curl -sL -A "Mozilla/5.0" "$URL" | tee /tmp/human.html | grep -iE 'og:title|og:image' | head
# Meta
curl -sL -A "facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)" \
"$URL" | tee /tmp/fb.html | grep -iE 'og:title|og:image' | head
# X
curl -sL -A "Twitterbot/1.0" "$URL" | tee /tmp/x.html | grep -iE 'og:title|og:image|twitter:' | head
# LinkedIn
curl -sL -A "LinkedInBot/1.0 (compatible; Mozilla/5.0; Apache-HttpClient +http://www.linkedin.com)" \
"$URL" | tee /tmp/li.html | grep -iE 'og:title|og:image' | head
然后比文档,不靠感觉:
# 正文哈希(忽略响应头日期;任何 HTML 漂移都会变)
sha256sum /tmp/human.html /tmp/fb.html /tmp/x.html /tmp/li.html
# 只比 meta
diff -u \
<(grep -iE 'property="og:|name="twitter:' /tmp/human.html | sort) \
<(grep -iE 'property="og:|name="twitter:' /tmp/fb.html | sort)
也要看 状态码与响应头:
curl -sI -A "facebookexternalhit/1.1" "$URL" | head -20
你 200、bot 403 或挑战页,是经典 WAF 误伤。可与空白卡片清单对照:为什么你的 Open Graph 卡片一片空白。
对 OG 而言什么叫「相同」
全文 HTML 完全一致最理想,但不总是必须。分享正确性至少要在各社交 UA 间一致:
og:title、og:description、og:image、og:url、og:type- 绝对 HTTPS 图片 URL,无需登录即可 200
- 不要用 bot 专用插页顶替真实文档
若营销 HTML 与 bot HTML 有意不同,把 bot 模板当成一等发布面写进发版清单——和换主视觉同优先级。
何时该统一 HTML(何时分叉可接受)
优先同一份 HTML,当:
- 你并没有在刻意维护单独的分享模板
- A/B 或边缘个性化会按 cookie 改标题 / 主视觉
- Bot 管理对公开营销 URL 出挑战页
- 「优化」只针对 Googlebot 或 CWV,却波及了 unfurl
有意分叉可以接受,当:
- 给爬虫 SSR 薄分享壳、给用户重客户端应用,且 OG 值来自同一事实源
- 仅为抓取体积去掉非分享 chrome,不改变 meta 含义
永远不 OK:
- 把隐私数据只放在非 bot 分支当「安全」
- 对 bot 长期返回错误 meta 的 200,人类却看到真活动
- 人类模板已发版、bot 模板忘了同步
OGKit 把意外分叉编码为 ua-content-diverged:不同 User-Agent 拿到不同 HTML body 哈希。这是 warn,不是自动判定「你在 cloaking」——但它是逼人眼看一眼的信号。
检查清单
- 不跑 JS 的
curl里能看到你期望的og:* -
curl -A facebookexternalhit/1.1(以及至少一个其他社交 UA)不被拦 - 各 UA 正文或 meta 哈希一致,或差异有意且有文档
- Bot 对抗规则对已知社交爬虫放行公开分享 URL
- 改标签 / 换图后走官方 rescrape,不依赖编造的 TTL
- 秘密靠鉴权,不靠 User-Agent
下一篇读什么
- Open Graph 到底在解决什么 — 完整分享工作流,不止写标签
- 为什么你的 Open Graph 卡片一片空白 — 五种失败模式
- 平台档案 — 在线 UA 字符串、图片预算与出处
- SPA / SSR 抓取缺口、缓存与 rescrape、CI 门禁 — 系列后续
做一次多 UA 扫描
把公网 URL 贴进首页扫描。OGKit 用与上表同一套平台档案里的 User-Agent 抓取,输出含 ua-content-diverged 在内的规则发现,并在 HTML 已对但卡片仍旧时指向官方 rescrape。
公网爬虫够不到的 localhost / 内网,走浏览器扩展路径——系列后面会写。产品要做的不是更漂亮的假卡片,而是摊开每个 bot 真正拿到的那份文档。