使用Python剥离和替换高unicode字符文档的最快方法是什么?

Rhu*_*arb 5 python unicode parsing text-processing ascii

我希望从大文档中替换所有高级unicode字符,例如重音Es,左右引号等,以及低范围中的"普通"对应字符,例如常规"E"和直引号.我需要经常在非常大的文档上执行此操作.我在这里看到了一个这样的例子:http://www.designmeme.com/mtplugins/lowdown.txt

有没有一种快速的方法在Python中执行此操作而不使用s.replace(...).replace(...).replace(...)...?我已经尝试过几个字符来替换,文档剥离变得非常慢.

编辑,我的unutbu代码版本似乎不起作用:

# -*- coding: iso-8859-15 -*-
import unidecode
def ascii_map():
    data={}
    for num in range(256):
        h=num
        filename='x{num:02x}'.format(num=num)
        try:
            mod = __import__('unidecode.'+filename,
                             fromlist=True)
        except ImportError:
            pass
        else:
            for l,val in enumerate(mod.data):
                i=h<<8
                i+=l
                if i >= 0x80:
                    data[i]=unicode(val)
    return data

if __name__=='__main__':
    s = u'“fancy“fancy2'
    print(s.translate(ascii_map()))
Run Code Online (Sandbox Code Playgroud)

unu*_*tbu 7

# -*- encoding: utf-8 -*-
import unicodedata

def shoehorn_unicode_into_ascii(s):
    return unicodedata.normalize('NFKD', s).encode('ascii','ignore')

if __name__=='__main__':
    s = u"éèêàùçÇ"
    print(shoehorn_unicode_into_ascii(s))
    # eeeaucC
Run Code Online (Sandbox Code Playgroud)

请注意,正如@Mark Tolonen所指出的,上面的方法删除了一些像ß''"这样的字符.如果上面的代码截断了您希望翻译的字符,那么您可能必须使用字符串的translate方法来手动修复这些问题.另一种选择是使用unidecode(参见JF Sebastian的回答).

当你有一个大的unicode字符串时,使用它的translate方法将比使用该replace方法快得多.

编辑: unidecode具有更完整的unicode代码点映射到ascii.但是,unidecode.unidecode循环遍历字符串(在Python循环中),这比使用该translate方法慢.

以下辅助函数使用unidecode的数据文件和translate方法可以获得更好的速度,尤其是对于长字符串.

在我对1-6 MB文本文件的测试中,使用ascii_map速度比使用速度快4-6倍unidecode.unidecode.

# -*- coding: utf-8 -*-
import unidecode
def ascii_map():
    data={}
    for num in range(256):
        h=num
        filename='x{num:02x}'.format(num=num)
        try:
            mod = __import__('unidecode.'+filename,
                             fromlist=True)
        except ImportError:
            pass
        else:
            for l,val in enumerate(mod.data):
                i=h<<8
                i+=l
                if i >= 0x80:
                    data[i]=unicode(val)
    return data

if __name__=='__main__':
    s = u"éèêàùçÇ"
    print(s.translate(ascii_map()))
    # eeeaucC
Run Code Online (Sandbox Code Playgroud)

Edit2:Rhubarb,如果# -*- encoding: utf-8 -*-导致SyntaxError,请尝试 # -*- encoding: cp1252 -*-.要声明的编码取决于文本编辑器用于保存文件的编码.Linux倾向于使用utf-8,而且(似乎也许)Windows倾向于使用cp1252.