提取社交分享圖片和開放圖譜標籤
提取社交分享圖片和開放圖譜標籤
Bun 的 HTMLRewriter API 通過將 CSS 選擇器與要處理的元素、文本和屬性進行匹配,從 HTML 中提取社交分享圖片和 Open Graph 後設資料。你可以使用它來建置連結預覽、社交媒體卡片或網頁抓取工具。
interface SocialMetadata {
title?: string;
description?: string;
image?: string;
url?: string;
site_name?: string;
type?: string;
}
async function extractSocialMetadata(url: string): Promise<SocialMetadata> {
const metadata: SocialMetadata = {};
const response = await fetch(url);
const rewriter = new HTMLRewriter()
// 提取開放圖譜(Open Graph)meta 標籤
.on('meta[property^="og:"]', {
element(el) {
const property = el.getAttribute("property");
const content = el.getAttribute("content");
if (property && content) {
// 將 "og:image" 轉換為 "image" 等等
const key = property.replace("og:", "") as keyof SocialMetadata;
metadata[key] = content;
}
},
})
// 作為備用,提取 Twitter Card meta 標籤
.on('meta[name^="twitter:"]', {
element(el) {
const name = el.getAttribute("name");
const content = el.getAttribute("content");
if (name && content) {
const key = name.replace("twitter:", "") as keyof SocialMetadata;
// Only use Twitter Card data if nothing has set this key yet (OG tags always overwrite it)
if (!metadata[key]) {
metadata[key] = content;
}
}
},
})
// 備用,提取普通 meta 標籤
.on('meta[name="description"]', {
element(el) {
const content = el.getAttribute("content");
if (content && !metadata.description) {
metadata.description = content;
}
},
})
// 備用,提取標題標籤
.on("title", {
text(text) {
if (!metadata.title) {
metadata.title = text.text;
}
},
});
// 處理響應內容
await rewriter.transform(response).blob();
// 將相對圖片 URL 轉換為絕對 URL
if (metadata.image && !metadata.image.startsWith("http")) {
try {
metadata.image = new URL(metadata.image, url).href;
} catch {
// 如果解析失敗,則保留原始 URL
}
}
return metadata;
}
// 範例用法
const metadata = await extractSocialMetadata("https://bun.sh");
console.log(metadata);
// {
// title: "Bun — A fast all-in-one JavaScript runtime",
// description: "Bundle, install, and run JavaScript & TypeScript — all in Bun. Bun is a fast JavaScript runtime & toolkit with a bundler, test runner, and npm-compatible package manager built in.",
// image: "https://bun.sh/share_v4.png",
// type: "website",
// ...
// }