ホームページ  >  記事  >  バックエンド開発  >  Pythonのブラックマジックエンコード変換方法

Pythonのブラックマジックエンコード変換方法

高洛峰
高洛峰オリジナル
2017-03-13 18:15:331116ブラウズ

この記事は主にpython黒魔術のエンコード変換を紹介し、興味のある友人はそれを参照してください

エンコード変換を行うために他の言語のライブラリを使用する場合、理解できません 通常処理される文字の種類は 2 つ (または 3 つ) だけです:

  • 例外をスローする

  • 代替文字に置き換える


しかし、複雑な現実世界では、さまざまな信頼性の低さにより、処理するテキストには混合エンコーディングなどの不一致要素が常に存在します。この場合、上記のアプローチに戻ります。

それでは、Python でもっと良い方法はあるのでしょうか?

答えは、そうです!

Python のエンコード変換プロセスは、実際には 2 段階の変換です:


source -> unicode -> dest

まず、

文字列を元のエンコードから Unicode に変換します。次に、Unicode をターゲットのエンコーディングに変換します。

最初のステップでは、通常、

decode()またはunicode()これら2つの関数を使用して完了します。 2 番目のステップでは、
encode() 関数を使用して完了します。

ここで話している黒魔術は、最初のステップで実現されます。

decode 関数と unicode 関数には両方とも

errors と呼ばれるオプションのパラメーターがあります。公式の説明を見てください:

  • エラーは、別のエラーを設定するために与えられる可能性があります

  • 。デフォルトは、エンコードエラーが発生することを意味する「strict」です

  • a UnicodeDecodeError。他の可能な値は、'ignore' と 'replace'

  • 、コーデックに登録されている他の名前です。
    UnicodeDecodeErrors を処理可能です。

  • このパラメータには通常、次の 3 つの値があります:

厳密なデフォルト値。エンコード エラーが発生した場合は、UnicodeDecodeError がスローされます。

  • スキップを無視してください。

  • を?に置き換えます。

  • さて、最後の文を見ましたか?ショーが始まります! モジュールコーデックには register_error という関数があります。この機能を使用すると、ユーザーはカスタムのエラー処理方法を登録できます。 UnicodeDecodeError を処理するために使用されます。

  • 関数のプロトタイプを見てみましょう:

codecs.register_error(name, error_handler)

name:

エラー処理

の名前。デコード関数のエラーパラメータを埋めるために使用されます。

error_handler: 処理関数。この関数は例外パラメータを受け入れます。

タプルには 2 つの要素があり、1 つ目はエラー修正された文字列であり、2 つ目はデコードを続行する開始位置です。具体的な実装を見てみましょう:

def cjk_error(e):
  if not isinstance(e, UnicodeDecodeError):
    raise TypeError("don't know how to handle %r" % exc) 
  if exc.end + 1 > len(exc.object): 
    raise TypeError('unknown codec ,the object too short!') 
  ch1 = ord(exc.object[exc.start:exc.end]) 
  newpos = exc.end + 1 
  ch2 = ord(exc.object[exc.start + 1:newpos]) 
  sk = exc.object[exc.start:newpos] 
  if 0x81<=ch1<=0xFE and (0x40<=ch2<=0x7E or 0x7E<=ch2<=0xFE): # GBK 
    return (unicode(sk,&#39;cp936&#39;), newpos) 
  if 0x81<=ch1<=0xFE and (0x40<=ch2<=0x7E or 0xA1<=ch2<=0xFE): # BIG5 
    return (unicode(sk,&#39;big5&#39;), newpos) 
  raise TypeError(&#39;unknown codec !&#39;) 
codecs.register_error("cjk_replace", cjk_replace)
上記は、私がインターネットから
コピー
したものです。最初はとても良いと思いましたが、後になって、それが非常に無反省なアルゴリズムであることがわかりました。

たとえば、utf8 と gbk には最初の 2 バイトに共通部分があります。 UTF8 文字列が gbk エンコードでデコードされると、3 バイト目からエラーが発生します (最初の 2 バイトは、gbk エンコード範囲の中国語文字に対応することもあります)。

例:


a = "你"              # utf8编码:&#39;\xe4\xbd\xa0&#39;
c = unicode(a[:2],&#39;gbk&#39;)  # 正常返回
c = unicode(a, &#39;gbk&#39;)    # UnicodeDecodeError 。错误发生在第三个字节

したがって、この状況では、次の改善を行いました:

import codec

def cjk_replace(e):
  if not isinstance(e, UnicodeDecodeError):
    raise TypeError("invalid exception type %s" e)

  src = e.encoding
  if src in (&#39;gbk&#39;,&#39;gb18030&#39;, &#39;big5&#39;):
    beg = e.start - 2
    if beg >= 0:
      try:
        return unicode(e.object[beg:e.end], &#39;utf8&#39;), e.end + 1
      except:
        pass

  if exc.end + 1 > len(exc.object):
    raise TypeError(&#39;unknown codec ,the object too short!&#39;)
  ch1 = ord(exc.object[exc.start:exc.end])
  newpos = exc.end + 1
  ch2 = ord(exc.object[exc.start + 1:newpos])
  sk = exc.object[exc.start:newpos]

  if src != &#39;gbk&#39; and 0x81<=ch1<=0xFE and (0x40<=ch2<=0x7E or 0x7E<=ch2<=0xFE): # GBK
    return (unicode(sk,&#39;cp936&#39;), newpos)
  if src != &#39;big5&#39; and 0x81<=ch1<=0xFE and (0x40<=ch2<=0x7E or 0xA1<=ch2<=0xFE): # BIG5
    return (unicode(sk,&#39;big5&#39;), newpos)
  raise TypeError(&#39;unknown codec !&#39;)

codecs.register_error("cjk_replace", cjk_replace)

もちろん、このロジックは実際には十分厳密ではありません。この混合エンコードの異常に対処するのは少し現実的ですが。

しかし、Python はそのような機能を提供しているので、どうすればもっと良くできるか、みんなで話し合うことができます

以上がPythonのブラックマジックエンコード変換方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。