Web をクロールしているときに、いくつかの非常に厄介な文字列に出くわしました。UTF-7
特に、あるページがであると宣伝していますがUTF-7
、それほど問題ではないようです。テキストの正確な意図を表現することには関心がありませんがUTF-8
、ダウンストリームでの消費に取り掛かる必要があるだけです。
私が直面している奇妙な点は、最初にエンコードしてからデコードできない文字列を取得できることです。unicode
UTF-8
エラーを表示しながら、できる限り文字列を抽出しました。
bytes = [43, 105, 100, 41, 46, 101, 95, 39, 43, 105, 100, 43]
string = ''.join(chr(c) for c in bytes)
# This particular string happens to be advertised as UTF-7, though it is
# a bit malformed. We'll ignore these errors when decoding it.
decoded = string.decode('utf-7', 'ignore')
# This decoded string, however, cannot be encoded into UTF-8 and back:
error = decoded.encode('utf-8').decode('utf-8')
Mac 10.5.7 の Python 2.7.1 と 2.6.7、CentOS の Python 2.7.2 と 2.6.8 など、多くのシステムでこれを試してみました。残念ながら、動作するために必要なマシンでは、Ubuntu 12.04 の Python 2.7.3 で失敗します。失敗したシステムでは、次のように表示されます。
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
File "/usr/lib/python2.7/encodings/utf_8.py", line 16, in decode
return codecs.utf_8_decode(input, errors, True)
UnicodeDecodeError: 'utf8' codec can't decode byte 0xf7 in position 4: invalid start byte
動作しているシステムと動作していないシステムで見られる中間値の一部を次に示します。
# Working:
>>> repr(decoded)
'u".e_\'\\u89df"'
>>> repr(decoded.encode('utf-8'))
'".e_\'\\xe8\\xa7\\x9f"'
# Non-working:
>>> repr(decoded)
'u".e_\'\\U089d89df"'
>>> repr(decoded.encode('utf-8'))
'".e_\'\\xf7\\x98\\xa7\\x9f"'
この 2 つは、最初のエンコード後には異なりますが、その理由はまだ謎です。2.7.2と 2.7.3 の間にこの動作を説明するものがないように見えるため、いくつかの文字テーブルまたは補助ライブラリが不足していることに問題があると思います。正常に動作するシステムでは、Unicode エンティティを印刷すると中国語の記号が表示されますが、表示されないシステムではプレースホルダーが表示されます。
これは私の質問に私を残します: そのような問題は誰にでもなじみがあるように見えますか、それとも問題が発生しているシステムで欠落している可能性のあるサポートライブラリを知っている人はいますか?