把页面链接贴到 LinkedIn / X / Slack / Telegram / 微信,预览卡片要么完全没图、要么显示一张早就改过的旧图——OG 协议的失败模式集中在三类:meta 标签写错(特别是相对路径)、图片本身不合规(尺寸 / 格式 / 大小),或者社交平台缓存了 24 小时前的爬取结果。本文按命中率排出 5 类原因,并给一条从 debugger 抓包到强制重爬的修复路径。
常见原因
按命中率从高到低。
1. og:image 用了相对路径
OG 爬虫不会做相对路径解析——它直接拿 content 里的字符串当 URL 请求。<meta property="og:image" content="/og.png"> 在浏览器里能渲染,爬虫却拿到 /og.png 这种无法 fetch 的字符串。
<!-- 错:相对路径,社交爬虫拿不到 -->
<meta property="og:image" content="/og/article-slug.png" />
<!-- 对:必须是绝对 URL,含 protocol -->
<meta property="og:image" content="https://yourdomain.com/og/article-slug.png" />
如何判断:用 LinkedIn Post Inspector / Twitter Card Validator / Facebook Sharing Debugger 输入你的 URL,看 og:image 字段值是不是 /xxx 开头。
2. 图片尺寸 / 比例不符合各平台要求
各平台有最小尺寸和宽高比硬限制,不达标直接不展示:
| 平台 | 推荐尺寸 | 最小 | 比例容忍 |
|---|---|---|---|
| Facebook / LinkedIn | 1200×630 | 600×315 | 1.91:1 |
| Twitter / X (summary_large_image) | 1200×628 | 300×157 | 2:1 |
| Slack | 1200×630 | 600×600 | 不限严格 |
| 微信 | 任意,但偏好 5:4 | 300×300 | — |
低于 600px 宽几乎所有平台都会拒绝展示。
如何判断:debugger 报错 Image size is too small 或预览里只显示标题不显示图。
3. 社交平台缓存了旧爬取
LinkedIn / Facebook / Twitter 抓取一次后会缓存 7 天到 30 天。你已经更新 og:image 但分享出来还是老图。
如何判断:debugger 里看到 “Last scraped: 5 days ago” 或类似时间戳;新 URL 第一次分享就有问题、老 URL 显示老图都是这一类。
4. 图片 URL 需要登录 / 加了 CORS 限制
og:image 指向了一个需要 cookie / token / referrer 的 CDN(比如 Cloudinary 的 signed URL),或者 origin 加了 Access-Control-Allow-Origin 白名单不包含社交爬虫 UA。
如何判断:
curl -A "facebookexternalhit/1.1" -I "https://yourdomain.com/og/article.png"
# 期望 200 + image/png;返回 403 / 401 / 重定向到登录页就是被挡了
5. 文件格式 / 大小超出限制
GIF / SVG / WebP 部分平台不支持;单图文件大小超 5MB(Facebook 上限 8MB、LinkedIn 5MB、Twitter 5MB)会被丢弃。
ls -lh og.png # 期望 < 1MB;超过 3MB 就有概率被拒
file og.png # 期望 PNG image data 或 JPEG image data
如何判断:debugger 报 Unsupported image format 或 Image too large。
最短修复路径
先用官方 debugger 看爬虫究竟拿到了什么,再针对性修。
Step 1:用各平台官方 debugger 抓一次爬取
| 平台 | URL |
|---|---|
| https://developers.facebook.com/tools/debug/ | |
| https://www.linkedin.com/post-inspector/ | |
| Twitter / X | 旧 Card Validator 已下线,用 https://opengraph.dev 替代 |
| Telegram | 在和 @WebpageBot 私聊里直接发 URL |
把 URL 粘进去,看:
og:image字段是不是绝对 URL- 抓到的图片预览是否正确
- 报错文案(如果有)
Step 2:检查 meta 标签是否齐全且为绝对 URL
最小有效配置:
<meta property="og:title" content="文章标题" />
<meta property="og:description" content="一句话摘要" />
<meta property="og:image" content="https://yourdomain.com/og/article.png" />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta property="og:url" content="https://yourdomain.com/articles/article-slug/" />
<meta property="og:type" content="article" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:image" content="https://yourdomain.com/og/article.png" />
Astro / Next.js 项目里用一个 helper 强制拼绝对 URL:
// src/lib/og.ts
const SITE = import.meta.env.PUBLIC_SITE_URL ?? "https://yourdomain.com";
export const absoluteOg = (path: string) =>
path.startsWith("http") ? path : `${SITE}${path.startsWith("/") ? "" : "/"}${path}`;
Step 3:验证图片本身可被爬虫 fetch
# 用社交爬虫的 User-Agent 拉一次
curl -A "facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)" \
-I "https://yourdomain.com/og/article.png"
# 期望响应:
# HTTP/2 200
# content-type: image/png
# content-length: < 5000000
返回 403 / 401 / 302 都说明被认证或权限挡了,需要把这条路径设为公开(CDN 白名单加上爬虫 UA,或把图片放到 public 静态目录)。
Step 4:让社交平台强制重新抓取
每个 debugger 都有”Scrape again” / “Re-scrape” / “Refresh” 按钮:
- Facebook Debugger:粘 URL → “Debug” → “Scrape Again”
- LinkedIn Post Inspector:粘 URL → 自动重新抓取(缓存约 7 天)
- Twitter (opengraph.dev):粘 URL → “Refresh”
- Telegram:和 @WebpageBot 私聊发 URL,回复中点 “refresh”
如果是大量页面要批量刷新,写脚本调用 Facebook Graph API 的 ?scrape=true:
curl -X POST "https://graph.facebook.com/?id=https://yourdomain.com/articles/foo&scrape=true&access_token=$FB_TOKEN"
Step 5:图片不合格时按规格重新导出
按 1200×630 PNG 或 JPEG 导出,文件大小控制在 300KB–1MB:
# ImageMagick 一键转换
convert input.png -resize 1200x630^ -gravity center -extent 1200x630 -quality 85 og.png
# 或 sharp (Node.js)
npx sharp-cli -i input.png -o og.png resize 1200 630 --fit cover
不要用 SVG(很多平台不支持)和 GIF(动图会被取首帧,常常很丑)。
预防建议
- OG 图片统一用 1200×630 PNG/JPG,文件控制在 1MB 以内;不要用 SVG / GIF / WebP。
- 用一个 helper 函数把 og:image / og:url 强制转成绝对 URL,避免每篇文章手写出错。
- 部署后在 CI 里跑一个 og-check 脚本:
curl -A facebookexternalhit ...拉每个新文章的 og:image,校验 200 + 正确 content-type。 - 新发布文章后立刻在 Facebook / LinkedIn debugger 触发一次 scrape,避免被默认 30 天缓存挡住前几天的分享。
- 用一个生成器(@vercel/og、satori、puppeteer)自动按标题生成 OG 图,杜绝”忘了配图”。