2

私はWindows8でPython3.3.0を使用しています。

requrl = urllib.request.Request(url) 

response = urllib.request.urlopen(requrl)

source = response.read()

source = source.decode('utf-8')

Webサイトにutf-8文字セットがある場合は正常に機能しますが、文字セットがある場合はどうなりますiso-8859-1charset。つまり、異なる文字セットで異なるWebサイトのURLを使用している可能性があります。では、複数の文字セットを処理する方法は?

この問題を次のように解決しようとしたときの私の努力をお話ししましょう。

    b1 = b'charset=iso-8859-1'
    b1 = b1.decode('iso-8859-1')

    if b1 in source:
            source = source.decode('iso-8859-1')

Soのようなエラーが発生TypeError: Type str doesn't support the buffer API したので、b1を文字列と見なしていると思います。これは正しい方法ではありません!:(

ソースコードの文字セットを手動で変更したり、Pythonのドキュメントを読んだりしないでください。私はすでにPython3のドキュメントに頭を入れようとしましたが、それでも運がないか、読むための正しいモジュール/コンテンツを選択していない可能性があります!

4

4 に答える 4

5

Python 3では、aは実際にはUnicode文字のシーケンスです( Python 2の構文にstr相当します)。u'mystring'返されるresponse.read()のはバイト文字列(一連のバイト)です。

失敗する理由は、バイト文字列内のUnicode文字シーケンスb1 in sourceを見つけようとしているためです。これは意味がないので失敗します。行を削除すると、2バイトシーケンスを比較しているため、機能するはずです。b1.decode('iso-8859-1')

ここで、根本的な問題に戻ります。複数の文字セットをサポートするには、文字セットを決定して、Unicode文字列にデコードする必要があります。これを行うには注意が必要です。Content-Type通常、応答のヘッダーを調べることができます。(以下のルールを参照してください。)ただし、非常に多くのWebサイトがヘッダーで間違ったエンコーディングを宣言しているため、html用の他の複雑なエンコーディングスニッフィングルールを開発する必要がありました。そのリンクを読んで、これがどんなに難しい問題であるかを理解してください!

私はあなたにどちらかをお勧めします:

  1. ほとんどのUnicode変換が自動的に適切に処理されるため、urllibの代わりにrequestsライブラリを使用してください。(使用もはるかに簡単です。)このレイヤーでのUnicodeへの変換が失敗した場合:
  2. lxml使用している基になるライブラリ(または)にバイトを直接渡してhtml5lib、エンコーディングの決定を処理できるようにしてください。多くの場合、ドキュメントタイプに適した文字セットスニッフィングアルゴリズムを実装しています。

これらのどちらも機能しない場合は、より積極的になり、chardetなどのライブラリを使用してエンコーディングを検出できますが、私の経験では、これを誤ってWebページに提供する人は無能であるため、混合エンコーディングドキュメントを作成することになります。何をしてもガベージキャラクター!

content-typeヘッダーで宣言された文字セットを解釈するためのルールは次のとおりです。

  1. 明示的な文字セットが宣言されていない場合:
    1. text / *(たとえば、text / html)はASCIIです。
    2. application / *(例:application / json、application / xhtml + xml)はutf-8です。
  2. 明示的な文字セットが宣言されている場合:
    1. タイプがtext/htmlで、文字セットがiso-8859-1の場合、実際にはwin-1252(== CP1252)です。
    2. それ以外の場合は、宣言された文字セットを使用します。

(html5仕様は、Content-TypeヘッダーよりもUTF8およびUTF16バイトマーカーを探すことにより、w3c仕様に故意に違反していることに注意してください。エンコード検出アルゴリズムのリンクを読んで、なぜ私たちが良いものを持てないのかを確認してください...)

于 2012-10-27T16:09:08.467 に答える
2

ここでの大きな問題は、多くの場合、Web ページで文字セットが定義されていても、Web ページのエンコーディングについて確信が持てないことです。ある文字セットを宣言しているが実際には別の文字セットにあるページ、または Content-Type ヘッダーとメタタグまたは xml 宣言で異なる文字セットを持っているページを十分に見てきました。

そのような場合chardetに役立ちます。

于 2012-10-27T15:41:18.060 に答える
1

オブジェクトstr内にバイトが含まれているかどうかを確認しています。bytes

>>> 'df' in b'df'
Traceback (most recent call last):
  File "<pyshell#107>", line 1, in <module>
    'df' in b'df'
TypeError: Type str doesn't support the buffer API

つまり、はい、オブジェクトを特定のエンコーディングでオブジェクトにデコードしたためb1、と見なされます。代わりに、の元の値と照合する必要があります。なぜそれをするのかは明らかではありません。strbytesstrb1.decode

于 2012-10-26T14:52:30.533 に答える
1

HTML 標準、Parsing HTML documents、Determin character setを参照してください(この目的には HTML5 で十分です)。

取るアルゴリズムがあります。あなたの目的のために要約すると、次のようになります。

  1. UTF-16 または UTF-8 の識別シーケンスを確認します (提供されたリンクを参照)
  2. HTTP によって提供される文字セットを使用します ( Content-Type ヘッダーを介して)
  3. エンコーディングを決定するためにバイト ストリームを事前スキャンするで少し後で説明するアルゴリズムを適用します。これは基本的に、ドキュメント内で「charset=」を検索して値を抽出することです。
于 2012-10-27T15:48:07.743 に答える