web-dev-qa-db-ja.com

JSoup文字エンコードの問題

JSoupを使用して http://www.latijnengrieks.com/vertaling.php?id=5368 からのコンテンツを解析しています。これはサードパーティのWebサイトであり、適切なエンコーディングを指定していません。次のコードを使用してデータをロードしています:

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.

方法はありますか?マークは出力で再びオリジナル(ü)になりますか?

23
Hihaatje

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.
_
49
BalusC

まあ、私はそれを行う別の方法を見つけました。私の場合、Jsoup Connectionオブジェクトがあり、「ISO-8859」でエンコードされたWebサイトのpost()リクエストからhtml応答を取得したいと思っていました。 JSOUPのデフォルトのエンコードはUTF-8であるため、応答からのコンテンツ(html)は、一部の文字を置き換える�で来ていました。どういうわけかそれをISO-8859-15に変換する必要がありました。そのために、接続を作成しました

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

その後、投稿の回答を保持する応答ドキュメントを作成しました。 Jsoupで応答のエンコードを設定する方法が明確ではなかったため、エンコードのプロパティを保持しながら、投稿を実行してから応答をバイトとして保存することにしました。その後、このバイト配列と適用する必要のある適切なエンコーディングを渡す新しい文字列を作成しました。その後、ドキュメントは正しいエンコーディングで作成されます。

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

したがって、response.html()を使用すると、変更の前後に戻りがあります。

前:

62.09-1-00-サポート、サポート、およびサービステクノロジと情報提供

後:

62.09-1-00-技術サポート、技術サポート、技術情報、情報提供

14
hugoeiji

Jsoupのドキュメントには、Jsoupがドキュメントを読み取るときに正しい文字セットを自動的に検出する必要があると記載されていますが、何らかの理由で私にとってはうまくいきません。次に、outputSettings()。charset(...)を使用してドキュメントの文字セットを手動で設定しようとしました。

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

しかし、それでもうまくいかなかったので、おそらく私はそれを間違っています(私はJsoupを学んでいるだけです)。

少なくとも私にとって機能した回避策の1つは、文字セットが設定されたスキャナーを使用してWebページを読み取ることでした。

     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を読み取るために別のクラスを使用する必要のない、より良い提案を誰かが思い付くかどうかを確認します。