Node.js 服务器渲染 HTML 文件为纯文本的完整方案
在实际开发中,我们经常需要在服务器端将 HTML 文件解析为纯文本。例如:生成文章摘要、进行全文搜索、数据清洗或用于语音合成。Node.js 提供了多种成熟的解决方案,本文将介绍最实用的几种方法,并给出完整的代码示例和注意事项。
解决方案一:使用 cheerio 库
cheerio 是一个轻量级的 HTML 解析库,语法类似 jQuery。它只解析 HTML 结构,不执行脚本,非常适合服务器端快速提取文本。
安装命令:
npm install cheerio
示例代码:从 HTML 字符串中提取所有文本(跳过 <script> 和 <style> 标签)。
const cheerio = require('cheerio');
function htmlToText(htmlContent) {
const $ = cheerio.load(htmlContent);
// 移除脚本和样式内容
$('script, style').remove();
// 获取 body 的纯文本,并用空格替换多余空白
const text = $('body').text() || $.root().text();
return text.replace(/\s+/g, ' ').trim();
}
// 示例用法
const html = '<div><h1>Hello World</h1><p>This is a <b>test</b>.</p></div>';
console.log(htmlToText(html)); // 输出: "Hello World This is a test."优点:速度快,依赖少。缺点:不能处理某些复杂嵌套或自闭合标签的极端情况。
解决方案二:使用 jsdom 库
jsdom 模拟浏览器环境,可以处理更复杂的 HTML 结构,甚至包含 JavaScript 动态生成的文本。但相对较重,适合需要 DOM 完整功能的场景。
安装:
npm install jsdom
示例代码:
const { JSDOM } = require('jsdom');
function htmlToTextJsdom(htmlContent) {
const dom = new JSDOM(htmlContent);
const doc = dom.window.document;
// 获取 body 或整个文档的文本
const body = doc.body || doc.documentElement;
return body.textContent.replace(/\s+/g, ' ').trim();
}
// 示例用法
const html = '<div><h1>Hello <span>World</span></h1></div>';
console.log(htmlToTextJsdom(html)); // 输出: "Hello World"注意:jsdom 处理时会自动渲染字符串中的 HTML 实体(如 & 转为 & 等),因此返回的文本已经是解码后的。
解决方案三:专用库 html-to-text
如果只需要将 HTML 转换为格式良好的纯文本(保留段落、列表、换行等),强烈推荐 html-to-text。该库内置了丰富的选项,能很好地处理标题、链接、图片等,并且支持自定义格式化规则。
安装:
npm install html-to-text
基础用法:
const { convert } = require('html-to-text');
function htmlToTextAdvanced(htmlContent) {
return convert(htmlContent, {
wordwrap: 130, // 自动换行宽度
selectors: [
{ selector: 'a', options: { hideLinkHrefIfSameAsText: true } },
{ selector: 'img', format: 'skip' } // 忽略图片
]
});
}
// 示例
const html = '<p>Click <a href="https://ipipp.com">here</a> to visit.</p><p>Another paragraph.</p>';
console.log(htmlToTextAdvanced(html));
/*
输出:
Click here to visit.
Another paragraph.
*/该库默认会保留段落间的空行,并自动解码 HTML 实体。如果需要更精细的控制,可以查看官方文档自定义选项。
性能对比与选型建议
| 库名称 | 性能 | 功能完整性 | 推荐场景 |
|---|---|---|---|
| cheerio | 高 | 中等(需手动处理特殊标签) | 简单文本提取、高并发服务 |
| jsdom | 低 | 高(完整 DOM) | 需要模拟浏览器环境 |
| html-to-text | 中等 | 高(专为文本转换设计) | 生成可读的纯文本、邮件正文 |
选择建议:如果只是移除 HTML 标签并获得连续文本,cheerio 最轻量;如果需要保持段落结构和可读性,html-to-text 是首选;除非必须执行页面脚本,否则不推荐 jsdom。
注意事项
- HTML 实体解码:绝大多数库会自动处理
<,>等实体。但手动拼接字符串时需使用he库或unescape函数。 - <script> 与 <style> 标签:务必在提取文本前移除这些标签,否则会混入代码与样式。
- 空白字符处理:根据最终用途,决定是否合并连续空格、保留换行或移除所有空白。
- 编码问题:如果 HTML 文件包含
<meta charset="gbk">,需要用iconv-lite先转码为 UTF-8。
完整示例:读取 HTML 文件并转为纯文本
以下示例使用 html-to-text 读取本地 HTML 文件,输出纯文本到控制台:
const fs = require('fs');
const path = require('path');
const { convert } = require('html-to-text');
function convertHtmlFileToText(filePath) {
const html = fs.readFileSync(filePath, 'utf-8');
const text = convert(html, { wordwrap: false });
return text;
}
// 使用示例
const filePath = path.join(__dirname, 'article.html');
const plainText = convertHtmlFileToText(filePath);
console.log(plainText);注意:wordwrap: false 可禁用自动换行,便于后续自定义处理。
总结
Node.js 服务器将 HTML 渲染为纯文本并非难事,根据需求选择合适的库即可。对于大多数生产环境,html-to-text 提供了最全面的功能,而 cheerio 则在性能敏感的场合更胜一筹。无论选择哪种方案,都需注意处理特殊标签和空白字符,以得到干净的纯文本结果。