html cheerio:获取普通+文本节点

bttbmeg0  于 2022-11-27  发布在  其他
关注(0)|答案(3)|浏览(266)

我正在使用cheerio解析不同节点中的HTML代码。我可以很容易地执行$("*"),但这只得到了普通的HTML节点,而不是单独的文本节点。让我们考虑3个用户输入:
第一:

text only
  • 我需要:单个文本节点。*

第二:

<div>
  text 1
  <div>
    inner text
  </div>
  text 2
</div>
  • 我需要:文本节点+ div节点+相同序列的文本节点。*

第三:

<div>
  <div>
    inner text 1
    <div>
      inner text 2
    </div>
  </div>
  <div>
    inner text 3
  </div>
</div>
  • 我需要:2个div节点 *

可能吗?

h43kikqp

h43kikqp1#

在希望帮助某人的时候,filter函数似乎也返回文本节点.我从这个答案中得到了帮助:https://stackoverflow.com/a/6520267/3800042

var $ = cheerio.load(tree);
var iterate = function(node, level) {
  if (typeof level === "undefined") level = "--";
  var list = $(node).contents().filter(function() { return true; });
  for (var i=0; i<=list.length-1; i++) {
    var item = list[i];
    console.log(level, "(" + i + ")", item.type, $(item).text());
    iterate(item, level + "--");
  }
}
iterate($.root());

HTML输入

<div>
  text 1
  <div>
    inner text
  </div>
  text 2
</div>

测试结果

-- (0) tag 

  text 1


    inner text


  text 2

---- (0) text 

  text 1


---- (1) tag 

    inner text


------ (0) text 

    inner text


---- (2) text 

  text 2
oalqel3c

oalqel3c2#

我希望下面的代码能对你有所帮助。

const cheerio = require("cheerio");
const htmlText = `<ul id="fruits">
  <!--This is a comment.-->
  <li class="apple">Apple</li>
  Peach
  <li class="orange">Orange</li>
  <li class="pear">Pear</li>
</ul>`;

const $ = cheerio.load(htmlText);
const contents = $('ul#fruits').contents();
console.log(contents.length);// 9, since nodes like '\n' are included 
console.log(new RegExp('^\\s*$').test('\n '));
function isWhitespaceTextNode(node){
    if(node.type !== 'text'){
        return false;
    }
    if(new RegExp('^\\s*$').test(node.data)){
        return true;
    }
    return false;
}
//Note here: filter is a function provided by cheerio, not Array.filter
const nonWhitespaceTextContents = contents.filter(nodeIndex=>{
    const node = contents[nodeIndex];
    if(isWhitespaceTextNode(node)){
        return false;
    }else{
        return true;
    }
});
console.log(nonWhitespaceTextContents.length);// 5, since nodes like '\n ' are excluded
nonWhitespaceTextContents.each((_, node)=>console.log(node));
//[comment node]
//[li node] apple
//[text node] peach
//[li node] orange
//[li node] pear
oipij1gg

oipij1gg3#

如果您想要节点的所有直接子节点,包括文字节点和标签节点,请使用.contents()并筛选出只有空白的文字节点。
下面是在示例中运行的代码:

const cheerio = require("cheerio"); // 1.0.0-rc.12

const tests = [
  // added a div container to make the parent selector consistent
  `<div>text only</div>`,

  `<div>
    text 1
    <div>
      inner text
    </div>
    text 2
  </div>`,

  `<div>
    <div>
      inner text 1
      <div>
        inner text 2
      </div>
    </div>
    <div>
      inner text 3
    </div>
  </div>`
];

tests.forEach(html => {
  const $ = cheerio.load(html);
  const result = [...$("div").first().contents()]
    .filter(e => e.type !== "text" || $(e).text().trim())

    // the following is purely for display purposes
    .map(e => e.type === "text" ? $(e).text().trim() : e.tagName);

  console.log(result);
});

输出量:

[ 'text only' ]
[ 'text 1', 'div', 'text 2' ]
[ 'div', 'div' ]

如果只需要文本节点而不需要标签,请参阅如何在Cheerio中获取由不同HTML标签分隔的文本。

相关问题