我厌倦了重复构建链接预览功能,于是把它做成了 API
Source: Dev.to

在过去的几年里,我构建的每个应用都需要同样的功能:粘贴一个 URL,显示预览卡片。Slack 这样做,Discord 也这样做,所有的 CMS 也是如此。每次我都要重新编写相同的 Cheerio 抓取代码,处理相同的 Open Graph 标签边缘情况,并且调试同样的问题——Twitter Cards 使用 name 而不是 property,而且网络上一半的人都写错了。
不久前,我终于把所有这些功能提取成一个独立的 API,并将其放在 RapidAPI 上。想想其他人也在写同样的代码。
实际返回内容
您传入一个 URL。您将获得跨六个层级的结构化元数据:
- Open Graph – 标题、描述、带尺寸的图片、文章元数据
- Twitter Cards – 卡片类型、站点、创建者;仅包含实际存在的标签,不进行回退猜测
- HTML meta – title 标签、meta description、canonical、主题颜色
- Icons – 自动选择质量最高的 favicon,使用优先级链
- Feeds – 发现 RSS、Atom 和 JSON Feed 链接
- JSON‑LD – 解析所有 script 块,优先使用
Article/Product而非BreadcrumbList
响应同时提供合并后的顶层视图(标题来源于有该信息的第一个源;先是 OG,然后是 Twitter,最后是 title 标签)以及原始解析层,以便您自行处理逻辑。
{
"title": "GitHub · Build and ship software on a single, collaborative platform",
"description": "Join the world's most widely adopted...",
"image": {
"url": "https://github.githubassets.com/images/modules/site/social-cards/campaign-social.png",
"width": 1200,
"height": 630
},
"favicon": "https://github.githubassets.com/favicons/favicon.svg",
"siteName": "GitHub",
"type": "website",
"themeColor": "#1e2327",
"openGraph": { ... },
"twitter": { ... },
"feeds": [],
"jsonLd": { "@type": "WebSite", ... },
"responseTime": 234
}正确处理起来令人烦恼的部分
OG 标签使用
property,Twitter 使用name。
Open Graph 规范写的是;Twitter Cards 写的是。很多站点会把它们互换使用,所以解析器会同时检查这两个属性的两种前缀。多个
og:image标签是合法的。
OG 规范通过重复标签来支持数组。像og:image:width这样的结构化属性会应用到最近声明的og:image。大多数抓取器只会获取第一个并忽略其余的。JSON‑LD 块非常混乱。
一个典型的新闻文章页面可能包含多个 JSON‑LD 块(例如BreadcrumbList、Organization和实际的Article)。需要解析所有块并挑选出正确的那个。Favicons 有优先级顺序。
Apple touch 图标(180×180)通常质量最高,其次是 32×32 的标准图标,最后是通用的/favicon.ico备选。大多数实现只会抓取它们找到的第一个 “。到处都是相对 URL。
OG 图片和 feed 链接常常是相对路径。需要使用实际的 URL(包括重定向后的地址)作为基准来正确解析它们。
The technical approach
该服务运行在托管于 VPS 的 Fastify 服务器上,使用 Cheerio 进行 HTML 解析。没有使用无头浏览器或 Puppeteer——仅仅抓取 HTML 并解析,确保缓存未命中时响应时间保持在 500 ms 以下,缓存命中时低于 5 ms。
SSRF 防护是耗时最长的部分。由于 API 接受任意 URL,它首先解析主机名,将得到的 IP 与私有地址段的阻止列表进行比对,然后直接连接解析后的 IP,以防止 DNS 重绑定攻击。
我还在同一套基础设施上构建了一个 Text Analytics API:传入文本即可返回可读性评分(Flesch‑Kincaid、Coleman‑Liau、SMOG 等)、关键词密度、二元组、三元组以及估计阅读时间。全部是对字符串的纯数学运算,响应时间低于 10 ms——对内容优化工具和写作助手非常有用。
试用它们
两个 API 都在 RapidAPI 上,提供免费套餐(每月 500 次请求):
- LinkPreview – URL 元数据提取
- TextAnalytics – 可读性评分、关键词密度、文本指标
免费套餐足以进行测试和原型开发。如果你遇到解析器处理不佳的边缘情况,我真的很想了解——解析互联网上的混乱 HTML 是一个永无止境的项目。