【问题标题】:cheerio: Get normal + text nodesCheerio:获取普通 + 文本节点
【发布时间】:2019-07-19 14:14:00
【问题描述】:

我正在使用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 节点

可能吗?

【问题讨论】:

    标签: javascript html node.js cheerio


    【解决方案1】:

    希望下面的代码可以帮助到你。

    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
    

    【讨论】:

      【解决方案2】:

      希望对某人有所帮助,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
      

      【讨论】:

      • "filter 函数似乎也返回文本节点。" - 这不是真的。代码中的过滤器行不执行任何操作:.filter(function() { return true; });。您需要过滤掉非文本类型:.filter(function() { return this.nodeType == Node.TEXT_NODE; });
      猜你喜欢
      • 1970-01-01
      • 2016-08-15
      • 1970-01-01
      • 1970-01-01
      • 2023-02-16
      • 1970-01-01
      • 2021-04-26
      • 2018-11-20
      • 1970-01-01
      相关资源
      最近更新 更多