如何解码cp1252字符串?
我正在使用eyeD3获取一个mp3标签(ID V1),想要了解它的编码方式。以下是我尝试的内容:
>>> print(type(mp3artist_v1))
<type 'unicode'>
>>> print(type(mp3artist_v1.encode('utf-8')))
<type 'str'>
>>> print(mp3artist_v1)
Zåìôèðà
>>> print(mp3artist_v1.encode('utf-8').decode('cp1252'))
ZåìôèðÃ
>>> print(u'Zемфира'.encode('utf-8').decode('cp1252'))
Zемфира
如果我使用一个在线工具来解码这个值,它会告诉我,值Zемфира
可以通过改变编码方式从CP1252 → UTF-8
转换为正确的值Zемфира
,而值Zåìôèðà
则可以通过改变编码方式为CP1252 → CP1251
来转换。
我应该怎么做才能从mp3artist_v1
中得到Zемфира
呢?.encode('cp1252').decode('cp1251')
这个方法效果不错,但我该如何自动识别可能的编码呢(只有三种编码可能:cp1251
、cp1252
、utf-8
)?我原本打算使用以下代码:
def forceDecode(string, codecs=['utf-8', 'cp1251', 'cp1252']):
for i in codecs:
try:
print(i)
return string.decode(i)
except:
pass
print "cannot decode url %s" % ([string])
但这并没有帮助,因为我需要先用一种字符集编码,然后再用另一种解码。
1 个回答
6
这个
s = u'Zåìôèðà'
print s.encode('latin1').decode('cp1251')
# Zемфира
解释:Zåìôèðà
被错误地当作了一个unicode字符串,但其实它只是一个字节序列,代表的是在cp1251编码下的Zемфира
。通过使用encode('latin1')
,我们把这个“unicode”字符串转换回字节,实际上是用字符的编码值作为字节值,然后再把这些字节转换回unicode,告诉解码器我们用的是cp1251编码。
至于自动解码,下面这种暴力破解的方法似乎能处理你的例子:
import re, itertools
def guess_decode(s):
encodings = ['cp1251', 'cp1252', 'utf8']
for steps in range(2, 10, 2):
for encs in itertools.product(encodings, repeat=steps):
r = s
try:
for enc in encs:
r = r.encode(enc) if isinstance(r, unicode) else r.decode(enc)
except (UnicodeEncodeError, UnicodeDecodeError) as e:
continue
if re.match(ur'^[\w\sа-яА-Я]+$', r):
print 'debug', encs, r
return r
print guess_decode(u'Zемфира')
print guess_decode(u'Zåìôèðà')
print guess_decode(u'ZåìôèðÃ\xA0')
结果:
debug ('cp1252', 'utf8') Zемфира
Zемфира
debug ('cp1252', 'cp1251') Zемфира
Zемфира
debug ('cp1252', 'utf8', 'cp1252', 'cp1251') Zемфира
Zемфира