我注意到很多网页都有多余的(出于我的目的)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
尝试删除它们,但我认为这会删除所有子元素/子元素即使它们在true
条件下与.ownText()
相匹配。
答案 0 :(得分:1)
您可以使用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>