我注意到很多网页都有多余的(对于我的目的而言)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()
规则 html
、head
和 body
元素也应该被删除。
如果您想防止某些特殊标签被删除,您可以使用一个简单的Set
或List
,其中包含标签名称,应保留:
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/