【问题标题】:Grab all text from html with Html Agility Pack使用 Html Agility Pack 从 html 中获取所有文本
【发布时间】:2011-05-10 02:47:17
【问题描述】:

输入

<html><body><p>foo <a href='http://www.example.com'>bar</a> baz</p></body></html>

输出

foo
bar
baz

我知道htmldoc.DocumentNode.InnerText,但它会给foobarbaz - 我想获取每个文本,而不是一次获取所有文本。

【问题讨论】:

    标签: c# html-agility-pack


    【解决方案1】:

    https://github.com/jamietre/CsQuery

    您尝试过 CsQuery 吗?虽然没有积极维护 - 它仍然是我将 HTML 解析为文本的最爱。这是从 HTML 获取文本的简单方法。

    var text = CQ.CreateDocument(htmlText).Text();
    

    这是一个完整的控制台应用程序:

    using System;
    using CsQuery;
    
    public class Program
    {
        public static void Main()
        {
            var html = "<div><h1>Hello World <p> some text inside h1 tag under p tag </p> </h1></div>";
            var text = CQ.CreateDocument(html).Text();
            Console.WriteLine(text); // Output: Hello World  some text inside h1 tag under p tag
    
        }
    }
    

    我知道 OP 只要求 HtmlAgilityPack,但 CsQuery 是另一个不受欢迎的解决方案,也是我发现的最佳解决方案之一,如果有人觉得这有帮助,我想分享。干杯!

    【讨论】:

      【解决方案2】:
      public string html2text(string html) {
          HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
          doc.LoadHtml(@"<html><body>" + html + "</body></html>");
          return doc.DocumentNode.SelectSingleNode("//body").InnerText;
      }
      

      此解决方法基于Html Agility Pack。也可以通过 NuGet 安装(包名:HtmlAgilityPack)。

      【讨论】:

      • 如果你的 html 参数有 标签,它会在将 html 转换为文本时将其转换为换行符(\n),这是不正确的。
      【解决方案3】:
      var pageContent = "{html content goes here}";
      var pageDoc = new HtmlDocument();
      pageDoc.LoadHtml(pageContent);
      var pageText = pageDoc.DocumentNode.InnerText;
      

      html内容的指定示例:

      <html><body><p>foo <a href='http://www.example.com'>bar</a> baz</p></body></html>
      

      将产生以下输出:

      foo bar baz
      

      【讨论】:

      • 这也将使 css 成为 pageText 的一部分,在我的情况下是不需要的
      【解决方案4】:

      我需要一个提取所有文本但丢弃脚本和样式标签内容的解决方案。我在任何地方都找不到它,但我想出了以下适合我自己的需要:

      StringBuilder sb = new StringBuilder();
      IEnumerable<HtmlNode> nodes = doc.DocumentNode.Descendants().Where( n => 
          n.NodeType == HtmlNodeType.Text &&
          n.ParentNode.Name != "script" &&
          n.ParentNode.Name != "style");
      foreach (HtmlNode node in nodes) {
          Console.WriteLine(node.InnerText);
      

      【讨论】:

      • 喜欢这个解决方案,它还剥离了 CSS 和脚本 :-)
      【解决方案5】:

      XPATH 是你的朋友 :)

      HtmlDocument doc = new HtmlDocument();
      doc.LoadHtml(@"<html><body><p>foo <a href='http://www.example.com'>bar</a> baz</p></body></html>");
      
      foreach(HtmlNode node in doc.DocumentNode.SelectNodes("//text()"))
      {
          Console.WriteLine("text=" + node.InnerText);
      }
      

      【讨论】:

      • 这对我来说非常有效。我扔给它的所有东西,甚至是旧 CMS 生成的蹩脚的 html 片段。
      • 不错。下面是一个小的修改,它也将处理没有文本的情况(从而避免运行时异常)。 HtmlNodeCollection textNodes = doc.DocumentNode.SelectNodes("//text()"); if (textNodes != null) foreach (textNodes 中的 HtmlNode 节点) result += node.InnerText;
      • @Josh 正是我所需要的
      【解决方案6】:
      var root = doc.DocumentNode;
      var sb = new StringBuilder();
      foreach (var node in root.DescendantNodesAndSelf())
      {
          if (!node.HasChildNodes)
          {
              string text = node.InnerText;
              if (!string.IsNullOrEmpty(text))
                  sb.AppendLine(text.Trim());
          }
      }
      

      这可以满足您的需要,但我不确定这是否是最好的方法。也许您应该迭代 DescendantNodesAndSelf 以外的其他内容以获得最佳性能。

      【讨论】:

        猜你喜欢
        • 2021-07-31
        • 1970-01-01
        • 2012-11-26
        • 2023-03-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-13
        相关资源
        最近更新 更多