在 NodeJS 中使用 Cheerio 将文本替换为 HTML
Replacing text with HTML using Cheerio in NodeJS
我想用标签替换结构化 HTML 中出现的所有单词。
例如,给定一个 HTML 这样的
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce porttitor, magna nec sollicitudin varius, ligula nisi finibus nulla, vel posuere libero erat eu tortor.
</p>
<p>
<ul>
<li>Lorem</li>
<li>ipsum</li>
<li>dolor</li>
<li>sit</li>
<li>amet</li>
</ul>
</p>
<p>
Lorem <b>ipsum</b> <span><em>dolor</em></span> sit amet, consectetur adipiscing elit.
</p>
我想用这个标签
替换所有出现的单词 'ipsum'
<a href="https://www.google.com/search?q=ipsum">ipsum</a>
在这种情况下,我尝试了一个非常简单的解决方案,但没有奏效:
const $ = cheerio.load(lorem_ipsum_html);
let words = $.text().trim().split(' ');
for (let t in words) {
let res = words[t];
if (words[t] == 'ipsum') res = '<a href="https://www.google.com/search?q=ipsum">ipsum</a>';
$.html().replace(words[t], res);
}
return $.html();
在这种情况下,函数 returns 未更改 html,即使替换看起来有效。
最重要的是,我还尝试移植了几个 jQuery 实现,例如:
Replace text with HTML element
运气不好。
1- 用 cheerio 加载正文
var $ = cheerio.load(body);
2- 使用这个递归函数,您可以替换所有元素及其子元素中的目标
function replacer($, text) {
if ($(text).children().length) {
$(text).children().each(function (itm) {
return replacer($, $(this));
});
}
else {
var value = $(text).text();
value = value.replace(/ipsum/g, '<a href="https://www.google.com/search?q=ipsum">ipsum</a>');
return $(text).text(value);
}
}
3- 用这个
将 cheerio dom 节点变回 html
return $.html(bb);
4- 将所有 "
、<
和 >
替换为正确的符号。
f(b).replace(/</g,'<').replace(/>/g, '>').replace(/"/g, '"')
希望对您有所帮助。只要修改你想要的代码
var b = `<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce porttitor, magna nec sollicitudin varius, ligula nisi finibus nulla, vel posuere libero erat eu tortor.
</p>
<p>
<ul>
<li>Lorem</li>
<li>ipsum</li>
<li>dolor</li>
<li>sit</li>
<li>amet</li>
</ul>
</p>
<p>
Lorem <b>ipsum</b> <span><em>dolor</em></span> sit amet, consectetur adipiscing elit.
</p>`;
var cheerio = require('cheerio');
function replacer($, text) {
if ($(text).children().length) {
$(text).children().each(function(itm) {
return replacer($, $(this));
});
} else {
var value = $(text).text();
value = value.replace(/ipsum/g, '<a href="https://www.google.com/search?q=ipsum">ipsum</a>');
return $(text).text(value);
}
}
function f(body) {
var $ = cheerio.load(body);
var bb = $("p").each(function(itm) {
return replacer($, $(this));
});
return $.html(bb);
}
console.log(f(b).replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"'))
输出:
<p>
Lorem <a href="https://www.google.com/search?q=ipsum">ipsum</a> dolor sit amet, consectetur adipiscing elit. Fusce porttitor, magna nec sollicitudin varius, ligula nisi finibus nulla, vel posuere libero erat eu tortor.
</p>
<p>
<ul>
<li>Lorem</li>
<li><a href="https://www.google.com/search?q=ipsum">ipsum</a></li>
<li>dolor</li>
<li>sit</li>
<li>amet</li>
</ul>
</p>
<p>
Lorem <b><a href="https://www.google.com/search?q=ipsum">ipsum</a></b> <span><em>dolor</em></span> sit amet, consectetur adipiscing elit.
我最终得到了这个(不太干净)的解决方案。这不是世界上最好的事情,但它确实有效。这里还有改进的空间。
let $ = cheerio.load(lorem_ipsum_html);
let words = $.text().trim().split(' ');
for (let t in words) {
let res = words[t];
if(words[t] == 'ipsum') res = '<a href="https://www.google.com/search?q=ipsum">ipsum</a>';
let $ = cheerio.load($.html().replace(words[t], res));
}
return $.html();
在这种情况下,HTML 结构保持不变,锚标记只是注入到正确的位置。
<p>
Lorem <a href="https://www.google.com/search?q=ipsum">ipsum</a> dolor sit amet, consectetur adipiscing elit. Fusce porttitor, magna nec sollicitudin varius, ligula nisi finibus nulla, vel posuere libero erat eu tortor.
</p>
<p>
<ul>
<li>Lorem</li>
<li><a href="https://www.google.com/search?q=ipsum">ipsum</a></li>
<li>dolor</li>
<li>sit</li>
<li>amet</li>
</ul>
</p>
<p>
Lorem <b><a href="https://www.google.com/search?q=ipsum">ipsum</a></b> <span><em>dolor</em></span> sit amet, consectetur adipiscing elit.
</p>
清洁解决方案:
这是通过迭代所有 dom 个文本节点来实现的代码:
const $ = require('cheerio').load(inputHtml);
const getTextNodes=(elem)=>elem.type==='text'?[]:
elem.contents().toArray()
.filter(el=>el!==undefined)//I don't know why some elements are undefined
.reduce((acc, el)=>
acc.concat(...el.type==='text'?[el]:getTextNodes($(el))), [] )
const replaceRegex = /ipsum/g;
const replacementTag = `<a href="https://www.google.com/search?q=ipsum">ipsum</a>`;
getTextNodes($(`html`))
.filter(node=>$.html(node).match(replaceRegex))
.map(node=>$(node).replaceWith($.html(node).replace(replaceRegex,replacementTag)) );
console.log($.html());
输出:
<html><head></head><body><p>
Lorem <a href="https://www.google.com/search?q=ipsum">ipsum</a> dolor sit amet, consectetur adipiscing elit. Fusce porttitor, magna nec sollicitudin varius, ligula nisi finibus nulla, vel posuere libero erat eu tortor.
</p>
<p>
</p><ul>
<li>Lorem</li>
<li><a href="https://www.google.com/search?q=ipsum">ipsum</a></li>
<li>dolor</li>
<li>sit</li>
<li>amet</li>
</ul>
<p></p>
<p>
Lorem <b><a href="https://www.google.com/search?q=ipsum">ipsum</a></b> <span><em>dolor</em></span> sit amet, consectetur adipiscing elit.
</p></body></html>
原回答
我想用标签替换结构化 HTML 中出现的所有单词。
例如,给定一个 HTML 这样的
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce porttitor, magna nec sollicitudin varius, ligula nisi finibus nulla, vel posuere libero erat eu tortor.
</p>
<p>
<ul>
<li>Lorem</li>
<li>ipsum</li>
<li>dolor</li>
<li>sit</li>
<li>amet</li>
</ul>
</p>
<p>
Lorem <b>ipsum</b> <span><em>dolor</em></span> sit amet, consectetur adipiscing elit.
</p>
我想用这个标签
替换所有出现的单词 'ipsum'<a href="https://www.google.com/search?q=ipsum">ipsum</a>
在这种情况下,我尝试了一个非常简单的解决方案,但没有奏效:
const $ = cheerio.load(lorem_ipsum_html);
let words = $.text().trim().split(' ');
for (let t in words) {
let res = words[t];
if (words[t] == 'ipsum') res = '<a href="https://www.google.com/search?q=ipsum">ipsum</a>';
$.html().replace(words[t], res);
}
return $.html();
在这种情况下,函数 returns 未更改 html,即使替换看起来有效。 最重要的是,我还尝试移植了几个 jQuery 实现,例如:
Replace text with HTML element
运气不好。
1- 用 cheerio 加载正文
var $ = cheerio.load(body);
2- 使用这个递归函数,您可以替换所有元素及其子元素中的目标
function replacer($, text) {
if ($(text).children().length) {
$(text).children().each(function (itm) {
return replacer($, $(this));
});
}
else {
var value = $(text).text();
value = value.replace(/ipsum/g, '<a href="https://www.google.com/search?q=ipsum">ipsum</a>');
return $(text).text(value);
}
}
3- 用这个
将 cheerio dom 节点变回 htmlreturn $.html(bb);
4- 将所有 "
、<
和 >
替换为正确的符号。
f(b).replace(/</g,'<').replace(/>/g, '>').replace(/"/g, '"')
希望对您有所帮助。只要修改你想要的代码
var b = `<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce porttitor, magna nec sollicitudin varius, ligula nisi finibus nulla, vel posuere libero erat eu tortor.
</p>
<p>
<ul>
<li>Lorem</li>
<li>ipsum</li>
<li>dolor</li>
<li>sit</li>
<li>amet</li>
</ul>
</p>
<p>
Lorem <b>ipsum</b> <span><em>dolor</em></span> sit amet, consectetur adipiscing elit.
</p>`;
var cheerio = require('cheerio');
function replacer($, text) {
if ($(text).children().length) {
$(text).children().each(function(itm) {
return replacer($, $(this));
});
} else {
var value = $(text).text();
value = value.replace(/ipsum/g, '<a href="https://www.google.com/search?q=ipsum">ipsum</a>');
return $(text).text(value);
}
}
function f(body) {
var $ = cheerio.load(body);
var bb = $("p").each(function(itm) {
return replacer($, $(this));
});
return $.html(bb);
}
console.log(f(b).replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"'))
输出:
<p>
Lorem <a href="https://www.google.com/search?q=ipsum">ipsum</a> dolor sit amet, consectetur adipiscing elit. Fusce porttitor, magna nec sollicitudin varius, ligula nisi finibus nulla, vel posuere libero erat eu tortor.
</p>
<p>
<ul>
<li>Lorem</li>
<li><a href="https://www.google.com/search?q=ipsum">ipsum</a></li>
<li>dolor</li>
<li>sit</li>
<li>amet</li>
</ul>
</p>
<p>
Lorem <b><a href="https://www.google.com/search?q=ipsum">ipsum</a></b> <span><em>dolor</em></span> sit amet, consectetur adipiscing elit.
我最终得到了这个(不太干净)的解决方案。这不是世界上最好的事情,但它确实有效。这里还有改进的空间。
let $ = cheerio.load(lorem_ipsum_html);
let words = $.text().trim().split(' ');
for (let t in words) {
let res = words[t];
if(words[t] == 'ipsum') res = '<a href="https://www.google.com/search?q=ipsum">ipsum</a>';
let $ = cheerio.load($.html().replace(words[t], res));
}
return $.html();
在这种情况下,HTML 结构保持不变,锚标记只是注入到正确的位置。
<p>
Lorem <a href="https://www.google.com/search?q=ipsum">ipsum</a> dolor sit amet, consectetur adipiscing elit. Fusce porttitor, magna nec sollicitudin varius, ligula nisi finibus nulla, vel posuere libero erat eu tortor.
</p>
<p>
<ul>
<li>Lorem</li>
<li><a href="https://www.google.com/search?q=ipsum">ipsum</a></li>
<li>dolor</li>
<li>sit</li>
<li>amet</li>
</ul>
</p>
<p>
Lorem <b><a href="https://www.google.com/search?q=ipsum">ipsum</a></b> <span><em>dolor</em></span> sit amet, consectetur adipiscing elit.
</p>
清洁解决方案:
这是通过迭代所有 dom 个文本节点来实现的代码:
const $ = require('cheerio').load(inputHtml);
const getTextNodes=(elem)=>elem.type==='text'?[]:
elem.contents().toArray()
.filter(el=>el!==undefined)//I don't know why some elements are undefined
.reduce((acc, el)=>
acc.concat(...el.type==='text'?[el]:getTextNodes($(el))), [] )
const replaceRegex = /ipsum/g;
const replacementTag = `<a href="https://www.google.com/search?q=ipsum">ipsum</a>`;
getTextNodes($(`html`))
.filter(node=>$.html(node).match(replaceRegex))
.map(node=>$(node).replaceWith($.html(node).replace(replaceRegex,replacementTag)) );
console.log($.html());
输出:
<html><head></head><body><p>
Lorem <a href="https://www.google.com/search?q=ipsum">ipsum</a> dolor sit amet, consectetur adipiscing elit. Fusce porttitor, magna nec sollicitudin varius, ligula nisi finibus nulla, vel posuere libero erat eu tortor.
</p>
<p>
</p><ul>
<li>Lorem</li>
<li><a href="https://www.google.com/search?q=ipsum">ipsum</a></li>
<li>dolor</li>
<li>sit</li>
<li>amet</li>
</ul>
<p></p>
<p>
Lorem <b><a href="https://www.google.com/search?q=ipsum">ipsum</a></b> <span><em>dolor</em></span> sit amet, consectetur adipiscing elit.
</p></body></html>
原回答