Java与Python间的多字节字符(UnicodeEncodeError)
我现在正在开发一个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 个回答
你已经在服务器上有了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中,D0
和A1
这两个字节组成了一个字符,但它们却被当成两个拉丁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')
但只有在你确认服务器上的数据已经是乱码之后,才可以这样做。