【问题标题】:How to search for comments ("<!-- -->") using Jsoup?如何使用 Jsoup 搜索评论(“<!-- -->”)?
【发布时间】:2019-10-10 23:45:16
【问题描述】:

我想从源 HTML 中删除这些标签及其内容。

【问题讨论】:

    标签: java jsoup


    【解决方案1】:

    搜索时,您基本上使用Elements.select(selector),其中selectorthis API 定义。但是 cmets 在技术上不是元素,所以你可能会在这里感到困惑,它们仍然是由节点名称 #comment 标识的节点。

    让我们看看它是如何工作的:

    import org.jsoup.Jsoup;
    import org.jsoup.nodes.Document;
    import org.jsoup.nodes.Node;
    
    public class RemoveComments {
        public static void main(String... args) {
            String h = "<html><head></head><body>" +
              "<div><!-- foo --><p>bar<!-- baz --></div><!--qux--></body></html>";
            Document doc = Jsoup.parse(h);
            removeComments(doc);
            doc.html(System.out);
        }
    
        private static void removeComments(Node node) {
            for (int i = 0; i < node.childNodeSize();) {
                Node child = node.childNode(i);
                if (child.nodeName().equals("#comment"))
                    child.remove();
                else {
                    removeComments(child);
                    i++;
                }
            }
        }        
    }
    

    【讨论】:

    • 如果你能得到一个 6 年前的 Jsoup 版本,它在当时就可以工作。否则,如果更新了 api,我欢迎修复更新此示例。看起来 childNodes list 在某些版本中是不可修改的。
    • 使用 JSoup 1.11.3 和 Groovy... 我需要做的唯一更改就是将 childNodesSize() 更改为 childNodeSize()。
    • @RobertHanson 谢谢,这可能是转录错误。
    【解决方案2】:

    使用 JSoup 1.11+(可能是旧版本),您可以应用过滤器:

    private void removeComments(Element article) {
        article.filter(new NodeFilter() {
            @Override
            public FilterResult tail(Node node, int depth) {
                if (node instanceof Comment) {
                    return FilterResult.REMOVE;
                }
                return FilterResult.CONTINUE;
            }
    
            @Override
            public FilterResult head(Node node, int depth) {
                if (node instanceof Comment) {
                    return FilterResult.REMOVE;
                }
                return FilterResult.CONTINUE;
            }
        });
    }
    

    【讨论】:

      【解决方案3】:

      参考@dlamblin https://stackoverflow.com/a/7541875/4712855此代码获取评论html

      public static void getHtmlComments(Node node) {
          for (int i = 0; i < node.childNodeSize();i++) {
              Node child = node.childNode(i);
              if (child.nodeName().equals("#comment")) {
                  Comment comment = (Comment) child;
                  child.after(comment.getData());
                  child.remove();
              }
              else {
                  getHtmlComments(child);
              }
          }
      }
      

      【讨论】:

        【解决方案4】:

        这是使用函数式编程方法的第一个示例的变体。查找作为当前节点的直接子节点的所有 cmets 的最简单方法是在 .childNodes() 的流上使用 .filter()

        public void removeComments(Element e) {
            e.childNodes().stream()
                .filter(n -> n.nodeName().equals("#comment")).collect(Collectors.toList())
                .forEach(n -> n.remove());
            e.children().forEach(elem -> removeComments(elem));
        }
        

        完整示例:

        package demo;
        
        import java.io.File;
        import java.io.FileOutputStream;
        import java.io.IOException;
        import java.io.PrintStream;
        import java.net.MalformedURLException;
        import java.net.URL;
        import java.util.stream.Collectors;
        
        import org.jsoup.Jsoup;
        import org.jsoup.nodes.Document;
        import org.jsoup.nodes.Element;
        public class Demo {
        
        public static void removeComments(Element e) {
            e.childNodes().stream()
                .filter(n -> n.nodeName().equals("#comment")).collect(Collectors.toList())
                .forEach(n -> n.remove());
            e.children().forEach(elem -> removeComments(elem));
        }
        
        public static void main(String[] args) throws MalformedURLException, IOException {
            Document doc = Jsoup.parse(new URL("https://en.wikipedia.org/"), 500);
        
            // do not try this with JDK < 8
            String userHome = System.getProperty("user.home");
            PrintStream out = new PrintStream(new FileOutputStream(userHome + File.separator + "before.html"));
            out.print(doc.outerHtml());
            out.close();
        
            removeComments(doc);
            out = new PrintStream(new FileOutputStream(userHome + File.separator + "after.html"));
            out.print(doc.outerHtml());
            out.close();
        }
        

        }

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-07-06
          • 1970-01-01
          • 2017-02-13
          • 2019-08-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多