java - 使用 Jsoup 删除不包含自己文本的节点

标签 java web-scraping jsoup

我注意到很多网页都有多余的(对于我的目的而言)html 节点。我想从页面中删除它们,因为这将使我的处理更容易。

有没有办法用 JSoup 来做到这一点?

为了让情况更清楚,假设我们有以下页面:

<html>
  <head>
  </head>
  <body>
    <div>I have some text</div>
    <div class='useless'>
      <div class='useless'>
        <div>I also have text
          <div>I also have text</div>
        </div>
      </div>   
    </div>      
  </body>
</html>

我想删除 class='useless' div - 但当然我不能通过它们的 class/id/tag 等来选择它们,因为它们没有内容。这当然会改变页面的结构,这完全没问题 - 它将使我的最终处理更容易。

结果将是:

<html>
  <head>
  </head>
  <body>
    <div>I have some text</div>
    <div class='useless'>
      <div class='useless'>
        <div>I also have text
          <div>I also have text</div>
        </div>
      </div>
    </div>   
  </body>
</html>

这可能以简单还是困难的方式实现。

结果将是:

<html>
  <head>
  </head>
  <body>
    <div>I have some text</div>
    <div>I also have text
      <div>I also have text</div>
    </div>  
  </body>
</html>

现在我想不出有什么特别优雅的事情。我的一般倾向是检查各种元素上的 ownText() 方法(将检查 ownText().length() > 0),如果 false code> 尝试删除它们,但我认为这也会删除任何子/子元素,即使它们与 .ownText() 条件匹配 true

最佳答案

您可以使用Document.getAllElements()并检查每个元素是否具有ownText()。如果它什么也不做。如果没有,则将所有子节点追加到父节点(如果有)。这应该可以完成工作:

Document document = Jsoup.parse(html);
document.getAllElements().stream()
        .filter(e -> e.ownText().isEmpty())
        .filter(Element::hasParent)
        .forEach(e -> {
            e.children().forEach(e.parent()::appendChild);
            e.remove();
        });

您共享的代码的结果将是这样的:

<div>
 I have some text
</div>
<div>
 I also have text 
 <div>
  I also have text
 </div> 
</div>

正如我在评论中提到的,您的 ownText() 规则 htmlheadbody 元素也应该被删除。

<小时/>

如果您想防止某些特殊标签被删除,您可以使用一个简单的SetList,其中包含标签名称,应保留:

Set<String> retainTagNames = new HashSet<>(Arrays.asList("html", "body"));
Document document = Jsoup.parse(html);
document.getAllElements().stream()
        .filter(e -> ! retainTagNames.contains(e.tagName()))
        .filter(e -> e.ownText().isEmpty())
        .filter(Element::hasParent)
        .forEach(e -> {
            e.children().forEach(e.parent()::appendChild);
            e.remove();
        });

结果将是:

<html>
 <head> 
 </head> 
 <body> 
  <div>
   I have some text
  </div>   
  <div>
   I also have text 
   <div>
    I also have text
   </div> 
  </div>
 </body>
</html>

关于java - 使用 Jsoup 删除不包含自己文本的节点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56434000/

相关文章:

java - 如何使用 Java 和 Spring 在 REST Web 服务中 wait()?

java - org.jsoup.Jsoup 不处理 javascript 链接?

java - 如何对 URL 进行编码以避免 Java 中的特殊字符?

java - 线程不可中断

java - Android - 具有 2 个源文件夹的项目的 gradle 构建失败

java - JSoup.connect 某些请求出现 403 错误

jsoup - 获取网页内容(通过AJAX调用加载)

python - 如何使用 beautifulsoup 从 url 中的表返回多个页面的数据

html - 如何在匹配组之间使用正则表达式从 html youtube 页面获取文本

python - 访问深层类层次结构中的所有 href 链接