UnicodeError
根本的なメカニズムを理解していないと、説明するのは難しいです。あなたは本当にどちらかまたは両方を読むべきです
(非常に小さな)一言で言えば、Unicodeコードポイントは1文字1を表す抽象的な「もの」です。文字列は一度に1文字ずつ来ると考えるので、プログラマーはこれらを操作するのが好きです。残念ながら、文字は1バイトのメモリに収まらなければならないことがかなり前に定められていたため、最大で256の異なる文字を使用できます。これは平易な英語には問題ありませんが、それ以外には機能しません。コードポイントのグローバルリスト(数千)があり、すべての可能な文字を保持することを目的としていますが、明らかに1バイトに収まりません。
解決策:文字列を作成するコードポイントの順序付きリストと、バイトシーケンスとしてのエンコードには違いがあります。文字列を操作するときは常に、これらの形式のどれに含めるべきかを明確にする必要があります。
フォーム間で変換するには.encode()
、コードポイントのリスト(Unicode文字列)をバイトのリストとして、.decode()
バイトをコードポイントのリストに変換します。そのためには、コードポイントをバイトに、またはその逆にマッピングする方法、つまりエンコーディングを知る必要があります。指定しない場合、Python2.xはASCIIを意味していると推測します。その推測が間違っている場合は、を取得しUnicodeError
ます。
Python 3.xは、バイトとコードポイントの区別がはるかに明確であるため、Unicode文字列の処理にはるかに優れていることに注意してください。
1種類。
編集:私はこれがどのように役立つかを指摘する必要があると思います。しかし、あなたは本当に上記のリンクを読むべきです!.encode()
sとsをどこにでも投げ込むの.decode()
はひどいコーディング方法であり、いつの日かあなたはもっとひどい問題に噛まれるでしょう。
とにかく、シェルで行っていることをステップスルーすると、次のように表示されます。
>>> from HTMLParser import HTMLParser
>>> text = "македонија"
>>> hparser = HTMLParser()
>>> text = hparser.unescape(text)
>>> text
u'\u043c\u0430\u043a\u0435\u0434\u043e\u043d\u0438\u0458\u0430'
ここではPython2.7を使用しているので、これはUnicode文字列、つまり一連のUnicodeコードポイントです。それらを次のような通常の文字列(つまり、バイトのリスト)にエンコードできます。
>>> text.encode("utf-8")
'\xd0\xbc\xd0\xb0\xd0\xba\xd0\xb5\xd0\xb4\xd0\xbe\xd0\xbd\xd0\xb8\xd1\x98\xd0\xb0'
ただし、別のエンコーディングを選択することもできます。
>>> text.encode("utf-16")
'\xff\xfe<\x040\x04:\x045\x044\x04>\x04=\x048\x04X\x040\x04'
使用するエンコーディングを決定する必要があります。
あなたがそれをしたときに何が悪かったのですか?ええと、すべてのエンコーディングがすべてのコードポイントを理解するわけではありません。特に、"ascii"
エンコーディングは最初の256のみを理解します。だからあなたがしようとすると
>>> text.encode("ascii")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-9: ordinal not in range(128)
これらのコードポイントをASCIIでエンコードできないため、エラーが発生するだけです。
あなたがそうするときreq.write
、あなたはリクエストの下にコードポイントのリストを書き込もうとしています。ただし、HTMLリクエストはコードポイントを理解しません。ASCIIを使用するだけです。Python 2は、Unicode文字列を自動的にASCIIエンコードすることで役立つように努めます。これは、実際にASCIIである場合は問題ありませんが、そうでない場合は問題ありません。
だからあなたはする必要がありますreq.write(hparser.unescape(text).encode("some-encoding"))
。