最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
当前位置: 首页 - 科技 - 知识百科 - 正文

python黑魔法之编码转换方法

来源:动视网 责编:小采 时间:2020-11-27 14:25:36
文档

python黑魔法之编码转换方法

python黑魔法之编码转换方法:这篇文章主要介绍了python黑魔法之编码转换,分析了python编码转换的方法,感兴趣的小伙伴们可以参考一下我们在使用其他语言的库做编码转换时,对于无法理解的字符,通常的处理也只有两种(或三种):抛异常替换成替代字符跳过但是在复杂的现实世界中,由于各
推荐度:
导读python黑魔法之编码转换方法:这篇文章主要介绍了python黑魔法之编码转换,分析了python编码转换的方法,感兴趣的小伙伴们可以参考一下我们在使用其他语言的库做编码转换时,对于无法理解的字符,通常的处理也只有两种(或三种):抛异常替换成替代字符跳过但是在复杂的现实世界中,由于各


这篇文章主要介绍了python黑魔法之编码转换,分析了python编码转换的方法,感兴趣的小伙伴们可以参考一下

我们在使用其他语言的库做编码转换时,对于无法理解的字符,通常的处理也只有两种(或三种):

  • 抛异常

  • 替换成替代字符

  • 跳过

  • 但是在复杂的现实世界中,由于各种不靠谱,我们处理的文本总会出现那么些不和谐因素,比如混合编码。在这种情况下,又回到了上面的处理办法。

    那么问题来了,python有没有更好地办法呢?

    答案是,有!

    python的编码转换流程实际上是两段式转换:

    source -> unicode -> dest

    首先将字符串从原始编码转换成unicode。再将unicode转换成目标编码。

    第一步我们一般采用decode()或者 unicode() 这两个函数完成。
    第二步我们使用encode()函数完成。

    在这里我们说的黑魔法就是在第一步实现。

    decode和unicode函数都有一个叫做errors的可选参数。看看官方的描述:

  • errors may be given to set a different error

  • handling scheme. Default is 'strict' meaning that encoding errors raise

  • a UnicodeDecodeError. Other possible values are 'ignore' and 'replace'

  • as well as any other name registered with codecs. register_error that is

  • able to handle UnicodeDecodeErrors.

  • 这个参数通常有三种值:

  • strict 默认值。如果出现编码错误,则会抛出UnicodeDecodeError。

  • ignore 跳过。

  • replace 用?替换。

  • 好了,看到最后一句话了吗?好戏上演了!

    模块codec有一个函数叫做register_error。他的作用让用户可以注册自定义的errors处理方法。
    用来处理UnicodeDecodeError。

    我们看看函数原型:

    codecs.register_error(name, error_handler)

    name: 错误处理的名称。用以填写在decode函数的error参数中。
    error_handler: 处理函数。该函数接受一个异常参数。
    返回一个tuple,该tuple有2个元素,第一个是纠错后的字符串,第二个是继续decode的起始位置

    有了上面的基本概念。我们看下具体实现:

    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,'cp936'), newpos) 
     if 0x81<=ch1<=0xFE and (0x40<=ch2<=0x7E or 0xA1<=ch2<=0xFE): # BIG5 
     return (unicode(sk,'big5'), newpos) 
     raise TypeError('unknown codec !') 
    codecs.register_error("cjk_replace", cjk_replace)

    上面这个是我从网上copy的。开始我觉得很不错,但是后来发现是个很不经推敲的算法。
    比如utf8和gbk在前两个字节就有交集的部分。当一个utf8的字符串以gbk编码decode的时候,出现错误是从第三个字节开始(前两个字节也能够在gbk编码范围中对应到一个汉字)。
    如:

    a = "你" # utf8编码:'xe4xbdxa0'
    c = unicode(a[:2],'gbk') # 正常返回
    c = unicode(a, 'gbk') # 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 ('gbk','gb18030', 'big5'):
     beg = e.start - 2
     if beg >= 0:
     try:
     return unicode(e.object[beg:e.end], 'utf8'), e.end + 1
     except:
     pass
    
     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 src != 'gbk' and 0x81<=ch1<=0xFE and (0x40<=ch2<=0x7E or 0x7E<=ch2<=0xFE): # GBK
     return (unicode(sk,'cp936'), newpos)
     if src != 'big5' and 0x81<=ch1<=0xFE and (0x40<=ch2<=0x7E or 0xA1<=ch2<=0xFE): # BIG5
     return (unicode(sk,'big5'), newpos)
     raise TypeError('unknown codec !')
    
    codecs.register_error("cjk_replace", cjk_replace)

    当然,这个逻辑其实还是不够严谨的。虽然对于这种混合编码这种畸形活处理有点较真儿。
    不过既然python提供这样的能力,大家可以一起来讨论下,我们怎么可以做的更好?

    文档

    python黑魔法之编码转换方法

    python黑魔法之编码转换方法:这篇文章主要介绍了python黑魔法之编码转换,分析了python编码转换的方法,感兴趣的小伙伴们可以参考一下我们在使用其他语言的库做编码转换时,对于无法理解的字符,通常的处理也只有两种(或三种):抛异常替换成替代字符跳过但是在复杂的现实世界中,由于各
    推荐度:
    标签: 转换 方法 代码
    • 热门焦点

    最新推荐

    猜你喜欢

    热门推荐

    专题
    Top