如何使用Cheerio和Node.js提取指定span标签对之间的文本?
如何使用Cheerio和Node.js提取指定span标签对之间的文本?
我明白你的困扰了——这个HTML结构确实有点棘手,section的起始标签和结束标签不仅跨了多个<p>元素,还夹杂着需要忽略的标题内容。你之前的代码只拿到section编号,主要是因为nextUntil的局限性:它只能查找当前元素的同级后续元素,没法获取到外面的<p>标签内容,再加上addBack()把section编号本身的文本也包含进去了,结果自然只有数字。
下面给你一套能解决这个问题的方案,我们手动遍历节点来收集文本,同时跳过不需要的标题:
const $ = cheerio.load(html); const sections = []; $("span.sectionno").each((_, sectionNoEl) => { // 获取section编号 const sectionNo = parseInt($(sectionNoEl).text().trim()); let currentNode = sectionNoEl.nextSibling; const textSegments = []; // 从sectionno的下一个节点开始,遍历直到遇到endsection while (currentNode) { // 遇到结束标签,停止遍历 if ($(currentNode).hasClass("endsection")) { break; } // 忽略h3标题元素,直接跳过 if (currentNode.tagName === "h3") { currentNode = currentNode.nextSibling; continue; } // 收集文本内容:区分文本节点和元素节点 if (currentNode.nodeType === 3) { // 处理纯文本节点,去掉多余空格 const text = currentNode.textContent.trim(); if (text) textSegments.push(text); } else if (currentNode.nodeType === 1) { // 处理元素节点(比如<p>),提取内部文本并去重空格 const text = $(currentNode).text().trim(); if (text) textSegments.push(text); } // 移动到下一个节点 currentNode = currentNode.nextSibling; } // 把收集到的文本片段合并成连贯的内容,清理多余空格 const fullText = textSegments.join(" ").replace(/\s+/g, " ").trim(); sections.push({ no: sectionNo, text: fullText }); }); console.log(sections);
代码逻辑解释:
- 遍历每个section起始标签:找到所有
span.sectionno,逐个处理。 - 从起始标签的下一个节点开始遍历:避免把section编号本身的文本算进去。
- 终止条件:一旦遇到
span.endsection就停止当前section的文本收集。 - 跳过标题:遇到
<h3>元素直接跳过,不收集其内容。 - 分类收集文本:区分纯文本节点(比如sectionno后面的直接文本)和元素节点(比如后续的
<p>),只保留非空的文本内容。 - 整理文本格式:把收集到的片段合并,用正则替换掉多余的空格和换行,得到干净连贯的文本。
运行这段代码后,就能得到你想要的结果啦:
[ { no: 1, text: "Do you see that shelf?" }, { no: 2, text: "The shelf is hanging on the wall beside the clock." }, { no: 3, text: "The clock was ticking slowly telling time" } ]
备注:内容来源于stack exchange,提问作者Adam D
相关产品推荐
相关产品推荐

