Java与Python间的多字节字符(UnicodeEncodeError)

0 投票
1 回答
716 浏览
提问于 2025-04-18 05:11

我现在正在开发一个Django应用,它会调用一个Java的REST API,并获取多语言的结果(这些结果最初是从Elasticsearch获取的)。我可以顺利地获取结果并把它们存储到一个对象里,但在JavaScript中显示这些结果时却出现了乱码——这本来应该是俄语:

乱码

当我尝试把它转换成字符串或者转换成unicode时,我得到了:

UnicodeEncodeError at /getObjectArticles
'ascii' codec can't encode characters in position 23-24: ordinal not in range(128)

我知道API返回的数据是好的,因为用Java应用调用时一切正常。有没有什么办法可以处理这个传入的字符串,让它变成可识别的字符呢?

编辑:我的数据处理代码..

g = requests.post(baseUrl, query_string)

except requests.exceptions.RequestException as e:
    print e

try:
    obj = g.json()
    articleTitle = obj['hit']['title']
    str(articleTitle)   # This results in a Unicode error
    articleTitle.decode("UTF-8")   # This results in a Unicode error

编辑:我的JavaScript/JQUERY代码

// Load article text
function getArticleText(articleId, index) {
    console.log($('#result_number').val());
    var es_url = gu.webapp_url + '/getArticle?articleId=' + encodeURIComponent(articleId) + "&index=" + encodeURIComponent(index);

    $.get(es_url).success(function(data) {
        console.log(data);
        var decodedText = $("<div/>").html(data.text).text();
        var decodedTitle = $("<div/>").html(data.articleTitle).text();

        // Close Article View Button
        $('#g2i2-article-info').html("<div id=\"closeArticleInfo\" class=\"closeWindow\">X</div>");

        // Article Info Table
        var articleTable = "<table class=\"table table-striped table-bordered table-condensed\">";
        articleTable = articleTable + "<tr><td>Title</td><td>" + decodedTitle + "</td></tr>";
        articleTable = articleTable + "<tr><td>Publication Date</td><td>" + data.pubDate + "</td></tr>";
        articleTable = articleTable + "<tr><td>Source Name</td><td>" + data.sourceName + "</td></tr>";
        articleTable = articleTable + "<tr><td>Location</td><td>" + data.locationName + "</td></tr>";
        articleTable = articleTable + "<tr><td>URL</td><td>" + data.url + "</td></tr>";
        articleTable = articleTable + "</table>"
        $('#g2i2-article-info').append(articleTable);

        // Article Text
        $('#g2i2-article-info').append(decodedText);
        $('#g2i2-article-info').css('display', 'block');

    }).error(function(jqXHR, textStatus, errorThrown) {
        console.log(textStatus + " " + errorThrown);
    });

}

1 个回答

1

你已经在服务器上有了Unicode数据;response.json()会为任何JSON字符串生成Unicode值,所以不需要再去解码了。

问题出在浏览器上,它产生了这种拉丁1乱码。浏览器接收到的是UTF-8(这是一种多字节编码),但它却把单个字节当成拉丁1字符来解释。比如,你的标题开头是西里尔字母Со,它是用UTF-8编码的,但浏览器错误地把它当成拉丁1来处理:

>>> u'Со'
u'\u0421\u043e'
>>> u'Со'.encode('utf8')
'\xd0\xa1\xd0\xbe'
>>> print u'Со'.encode('utf8').decode('latin1')
Со

所以在UTF-8中,D0A1这两个字节组成了一个字符,但它们却被当成两个拉丁1字符来显示。

Ñ这个字符是D1字节,后面可以跟大约33个不可打印的UTF-8字节,形成从рѠ范围内的字符。接下来是и,其实是и,等等。

你需要弄清楚为什么浏览器认为你的数据是拉丁1编码。

通常,这个问题是由发送给浏览器的Content-Type头决定的;如果它设置为text/html; charset=ISO-8859-1,那么浏览器就会把所有文本都当成拉丁1来处理。可能是你的HTML页面里有一个<meta>标签,比如<meta charset="ISO-8859-1">或者<meta http-equiv="Content-Type" content="text/html; charset="ISO-8859-1">,这些标签都可能导致类似的乱码效果。

另一种可能是你明确地把数据编码成了UTF-8,然后在某个地方又把它解码成了拉丁1,然后再发送给浏览器。

还有第三种可能是你使用的JSON服务本身就给你发送了拉丁1字节的JSON Unicode字符串,这样就产生了乱码。在这种情况下,你仍然可以通过先编码成拉丁1再从UTF-8解码来修复它:

fixed = broken.encode('latin1').decode('utf8')

但只有在你确认服务器上的数据已经是乱码之后,才可以这样做。

撰写回答