【问题标题】:JSoup character encoding issueJSoup 字符编码问题
【发布时间】:2011-12-03 22:38:41
【问题描述】:

我正在使用 JSoup 解析来自 http://www.latijnengrieks.com/vertaling.php?id=5368 的内容。这是第三方网站,没有指定正确的编码。我正在使用以下代码来加载数据:

public class Loader {

    public static void main(String[] args){
        String url = "http://www.latijnengrieks.com/vertaling.php?id=5368";

        Document doc;
        try {

            doc = Jsoup.connect(url).timeout(5000).get();
            Element content = doc.select("div.kader").first();
            Element contenttableElement = content.getElementsByClass("kopje").first().parent().parent();

            String contenttext = content.html();
            String tabletext = contenttableElement.html();

            contenttext = Jsoup.parse(contenttext).text();
            contenttext = contenttext.replace("br2n", "\n");
            tabletext = Jsoup.parse(tabletext.replaceAll("(?i)<br[^>]*>", "br2n")).text();
            tabletext = tabletext.replace("br2n", "\n");

            String text = contenttext.substring(tabletext.length(), contenttext.length());
            System.out.println(text);


        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }


    }    

}

这给出了以下输出:

Aeneas dwaalt rond in Troje en zoekt Cre?sa. Cre?sa is echter op de vlucht gestorven Plotseling verschijnt er een schim. Het is de schim van Cre?sa. De schim zegt:'De oorlog woedt!' Troje is ingenomen! Cre?sa is gestorven:'Vlucht!' Aeneas vlucht echter niet. Dan spreekt de schim:'Vlucht! Er staat jou een nieuw vaderland en een nieuw koninkrijk te wachten.' Dan pas gehoorzaamt Aeneas en vlucht.

有什么办法吗?标记可以在输出中再次成为原始(ü)吗?

【问题讨论】:

  • Jsoup 可能解析正确。你如何可视化输出?在控制台窗口中?作为写入文件的文本?
  • 最终输出会在一个 android TextView 中,但这是一个控制台窗口,android logcat 给出了相同的结果。

标签: java jsoup


【解决方案1】:

Jsoup 文档指出 Jsoup 在读取文档时应该自动检测正确的字符集,但由于某种原因,它对我不起作用。然后我尝试使用 outputSettings().charset(...) 手动设置文档的字符集:

doc.outputSettings().charset("ISO-8859-1");

但这仍然不起作用,所以也许我做错了(我只是在学习 Jsoup)。

至少对我来说确实有效的一种解决方法是使用具有字符集集的扫描仪读取网页:

     String charset = "ISO-8859-1";

     URL myUrl = new URL(url);
     Scanner urlScanner = new Scanner(myUrl.openStream(), charset);
     StringBuilder sb = new StringBuilder();
     while (urlScanner.hasNextLine()) {
        sb.append(urlScanner.nextLine() + "\n");
     }
     urlScanner.close();

     doc = Jsoup.parse(sb.toString());

但我会关注这个帖子,看看是否有人提出更好的建议,不需要使用另一个类来读取 HTML。

【讨论】:

  • 就我而言,我使用 UTF-8 处理中文文本!还是谢谢!
【解决方案2】:

HTTP 响应 Content-Type 标头中缺少 charset 属性。 Jsoup 在解析 HTML 时会使用平台默认字符集。 Document.OutputSettings#charset() 不起作用,因为它仅用于演示(在 html()text() 上),而不是用于解析数据(换句话说,已经太晚了)。

您需要将 URL 读取为 InputStream 并在 Jsoup#parse() 方法中手动指定字符集。

String url = "http://www.latijnengrieks.com/vertaling.php?id=5368";
Document document = Jsoup.parse(new URL(url).openStream(), "ISO-8859-1", url);
Element paragraph = document.select("div.kader p").first();

for (Node node : paragraph.childNodes()) {
    if (node instanceof TextNode) {
        System.out.println(((TextNode) node).text().trim());
    }
}

这会导致

Aeneas dwaalt rond in Troje en zoekt Creüsa.
Creüsa is echter op de vlucht gestorven
Plotseling verschijnt er een schim.
Het is de schim van Creüsa.
De schim zegt:'De oorlog woedt!'
Troje is ingenomen!
Creüsa is gestorven:'Vlucht!'
Aeneas vlucht echter niet.
Dan spreekt de schim:'Vlucht! Er staat jou een nieuw vaderland en een nieuw koninkrijk te wachten.'
Dan pas gehoorzaamt Aeneas en vlucht.

【讨论】:

  • 这就是我正在寻找的答案!再次感谢 Balus,如果可以的话,感谢 5+!
  • @Hovercraft:不客气。顺便说一句,乔纳森为即将到来的 Jsoup 1.6.2 添加了Element#textNodes(),这应该使instanceof 检查是多余的。你可以做for (TextNode node : paragraph.textNodes())。另见stackoverflow.com/questions/7164376/…
  • 实际上,当使用 Jsoup.parse(someText) 方法调用时,具有有效字符集的“Content-Type”的存在不会改变 Jsoup 的行为。您需要调用 Jsoup.parse(inputStream, null, baseUrl) 或一些类似的方法让 Jsoup 检测字符集。
  • 这个答案也可以解决 urls 包含其他字符。伟大的! @BalusC
  • 这种方式可以加参数吗?同样 Jsoup.connect(url).data(params)
【解决方案3】:

嗯,我想出了另一种方法来做到这一点。在我的例子中,我有一个 Jsoup Connection 对象,我想从一个用“ISO-8859”编码的网站中的 post() 请求中检索 html 响应。由于 JSOUP 的默认编码是 UTF-8,因此来自响应的内容(html)带有 � 替换了一些字母。我需要以某种方式将其转换为 ISO-8859-15。为此,我创建了连接

Connection connectionTest = Jsoup.connect("URL")
.cookie("cookiereference", "cookievalue")
.method(Method.POST);

之后,我创建了一个包含帖子答案的响应文档。由于不清楚如何在 Jsoup 中设置响应的编码,我选择执行帖子,然后将响应保存为字节,保留编码属性。之后,我创建了一个新的 String 传递这个 Byte 数组和必须应用的正确编码。之后,将使用正确的编码创建文档。

Document response = Jsoup.parse(new String(
connectionTest.execute().bodyAsBytes(),"ISO-8859-15"));

所以,当我们使用response.html()时,有修改前后的返回

之前:

62.09-1-00 - 支持技术、制造和服务于信息技术技术

之后:

62.09-1-00 - 技术支持、制造和服务支持 em tecnologia da informação

【讨论】:

  • 您不能将上述方法用作一般方法。如果您使用另一种编码访问的网站将如何工作。我们能不能把它概括一下。或者具体来说,如果网站在 ISO-8859 中,则运行此代码,否则运行默认 ( Jsoup.parse(execute.body(), url))
【解决方案4】:

我用过:

public static String charset = "UTF-8";
doc = Jsoup.parse(new URL(theURL).openStream(), charset, theURL);

另外,将类保存为 UTF-8

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-03-24
    • 1970-01-01
    • 1970-01-01
    • 2021-01-09
    • 2012-02-27
    • 2013-04-21
    相关资源
    最近更新 更多