如何在Jsoup解析中避免包含HTML头标签

25

我使用Jsoup来解析给定的HTML内容。在Jsoup.parse()之后,输出会将html、head和body标签附加到输入中。我只想忽略它们。

样例输入:

<p><b>This <i>is</i></b> <i>my sentence</i> of text.</p>

Java代码:

import java.io.File;
import java.io.IOException;

import org.apache.commons.io.FileUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

public class HTMLParse {

    public static void main(String args[]) throws IOException {
        try{
            File input = new File("/ab.html");
            String html = FileUtils.readFileToString(input, null);

            Document doc = Jsoup.parseBodyFragment(html);
            doc.outputSettings().prettyPrint(false);
            System.out.println(doc.html());
        }
        catch(Exception e){
            e.printStackTrace();
        }
    }
}

实际输出:

<html><head></head><body><p><b>This <i>is</i></b> <i>my sentence</i> of text.</p>
    </body></html>

预期输出:

<p><b>This <i>is</i></b> <i>my sentence</i> of text.</p>

请帮忙。


这应该会对你有所帮助。http://stackoverflow.com/questions/17492396/jsoup-filter-out-only-some-tags-from-html-to-text - RandomQuestion
@Jitendra 我想要像这样的属性。http://nekohtml.sourceforge.net/faq.html#fragments - Roshan
4个回答

26

原因:

parseBodyFragment() 以及所有其他 parse() 方法默认使用 HTML 解析器。这些方法总是会添加 HTML 壳(<html>…</html><head>…</head> 等)。

解决方案:

不要使用 HTML 解析器,改用 XML 解析器

Document doc = Jsoup.parse(html, "", Parser.xmlParser());

替换那一行代码,你的问题就会得到解决。

例子:

final String html = "<p><b>This <i>is</i></b> <i>my sentence</i> of text.</p>";

Document docHtml = Jsoup.parse(html);
Document docXml = Jsoup.parse(html, "", Parser.xmlParser());

System.out.println("******* HTML *******\n" + docHtml);
System.out.println();
System.out.println("*******  XML *******\n" + docXml);

输出:

******* HTML *******
<html>
 <head></head>
 <body>
  <p><b>This <i>is</i></b> <i>my sentence</i> of text.</p>
 </body>
</html>

*******  XML *******
<p><b>This <i>is</i></b> <i>my sentence</i> of text.</p>

7
这种方法的潜在缺陷是你无法获得任何HTML整理的效果。XML解析器不关心HTML5的结构,并且会将内容原样传递。如果您想要整理过的HTML正文,请使用Jsoup.parseBodyFragment(html).body(); - Jonathan Hedley
7
只有当你的HTML是XML时,这才适用。不幸的是,如果你有未结束的img标签之类的内容,XML解析器将假定接下来的标签都在其中。 - jwepurchase
1
我可以理解如果你已经在使用XML,但仅仅为了这个用例而依赖于XML并不是一个好主意。 - Alkanshel

15
为了获得预期的输出,实际上应该是:

为了得到期望的输出,实际上应该这样做:

final String html = "<p><b>This <i>is</i></b> <i>my sentence</i> of text.</p>";
Document doc = Jsoup.parseBodyFragment(html);
doc.outputSettings().prettyPrint(false);

System.out.println(doc.body().html());

12

您可以尝试使用XML解析器,但这并不总是有效,因为HTML并不总是XML;它通常有未终止的标签,如<img><br>。最好使用HTML解析器。您可以依赖于存在<html><head><body>标签,并且它们很容易被丢弃。只需通过选择body标签获取您的HTML片段,并请求其HTML即可。

Document doc = Jsoup.parseBodyFragment(html);
        doc.outputSettings().prettyPrint(false);
        System.out.println(doc.select("body").html());

2
因为警告XML解析器而点赞。尽管我使用jsoup来更正图像,但我几乎做了那件事。此外,我想评论一下,对body元素使用.html()只会得到内部HTML,不包括周围的body标签。 - Taugenichts

3
你可以使用 Jsoup.parse 方法,同时选择 HTML 解析器。你所需要做的就是去掉 htmlbody 标签。
这可以通过选择 body 元素并将其取消包装来完成。
String input = "<p><b>This <i>is</i></b> <i>my sentence</i> of text.</p>";
Node content = Jsoup.parse(input).body().unwrap();
System.out.println(content.html());

通过 body() 方法,您可以选中 body 元素;通过 unwrap() 方法,您可以移除 body 元素,只保留其内容。
因此输出结果为:
<p><b>This <i>is</i></b> <i>my sentence</i> of text.</p>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接