示例说明
服务端解析 HTML 需要的是选择器能力而非完整浏览器。Cheerio 实现 jQuery 风格 API,加载静态标记后即可查询 meta 标签属性、遍历标题、抽取正文文本。因为不执行脚本、不加载资源,内存与 CPU 成本比无头浏览器低一个量级,适合批量抓取链接预览与内容归档。
技术要点
- meta 选择器优先取 og 标签再回退到基础标签
- map 加 get 把节点集合转为纯数组
- 空白规整后统计词数评估正文质量
代码解读
metadata 的每个字段都用空值合并运算符提供回退链:og:title 缺失时退回 title 标签文本,canonical 与图片可能不存在故显式置 null。headings 用 map 提取每个 h2 的文本并过滤空值取前五条。wordCount 先把连续空白折叠为单空格再按空格分词计数。
使用建议
抓取要遵守站点的 robots 协议与频率礼仪,并发抓取务必限速。选择器要写防御式回退,页面改版时字段缺失不至于抛错。需要执行 JS 的动态页面再考虑无头浏览器方案。
代码示例
import * as cheerio from 'cheerio';
const html = await fetch('https://example.com/article')
.then((r) => r.text());
const $ = cheerio.load(html);
const metadata = {
title: $('meta[property="og:title"]').attr('content')
?? $('title').text().trim(),
description: $('meta[name="description"]').attr('content') ?? '',
canonical: $('link[rel="canonical"]').attr('href') ?? null,
image: $('meta[property="og:image"]').attr('content') ?? null,
};
const headings = $('h2')
.map((_, el) => $(el).text().trim())
.get()
.filter((t) => t.length > 0)
.slice(0, 5);
const wordCount = $('article')
.text()
.replace(/\s+/g, ' ')
.trim()
.split(' ')
.filter(Boolean).length;
console.log(JSON.stringify(metadata, null, 2), headings, wordCount);