python正则表达式模块无法使用utf-8(Devnagari)

时间:2013-05-26 08:44:44

标签: python regex utf-8 nlp

我在Bodo语言中使用python 2.7 for NLP(使用Devnagari脚本)

在停止删除单词的过程中,我在由换行符(“\ n”)分隔的文件中列出了停用词。我使用编解码器模块读取此文件并转换为列表。

raw_txt = codecs.open('stopwords.txt', 'r', 'utf-8')
stopWords = []
while(1):
    line = raw_txt.readline()
    if not line:
        break
    line = u''.join(line.strip())
    stopWords.append(line)

现在我编译了一个正则表达式来查找匹配的单词:

def addWordBoundary(word):       
    return u''.join(r"\b" + word + r"\b")

reg = regex.compile(r"(%s)" % "|".join(map(addWordBoundary, stopWords)), regex.UNICODE)

我使用codecs模块将语料库(文本文件)读取到字符串和regex.sub(),然后使用编解码器本身将其写入文件。但它错过了一些话。我无法弄清楚原因。

fl = codecs.open('corpus.txt', 'r', 'utf-8')
rawFile = fl.read()

cleanText = reg.sub('', rawFile, regex.U)

wr = codecs.open('output.txt', 'w', 'utf-8')
wr.write(cleanText)
wr.close()

出于测试目的,将其用作stopwords.txt和corpus.txt

  

माब्लानिफ्रायथो
  फारसेनिफ्रायबो
  रावनिफ्रायबो
  माब्लानिफ्राय
  जेब्लानिफ्राय
  अब्लानिफ्राय
  इफोरनिफ्राय
  नोंनिफ्रायबो
  फारसेनिफ्राय
  नोंनिफ्रायनो

output.txt文件必须是空文件,但它包含:

  

रावनिफ्रायबो
  इफोरनिफ्राय

此代码适用于英文文本(ASCII),因此我可能在使用utf-8处理时出错了。请建议。

1 个答案:

答案 0 :(得分:2)

您提供的文件中的某些停用词以未定义为字母数字的字符开头或结尾:

import unicodedata as ud
for w in stopWords:
    for c in w[0], w[-1]:
        print repr(c), ud.category(c),
    print
u'\u092e' Lo u'\u094b' Mc
u'\u092b' Lo u'\u094b' Mc
u'\ufeff' Cf u'\u094b' Mc
u'\u092e' Lo u'\u092f' Lo
u'\u091c' Lo u'\u092f' Lo
u'\u0905' Lo u'\u092f' Lo
u'\ufeff' Cf u'\u092f' Lo
u'\u0928' Lo u'\u094b' Mc
u'\u092b' Lo u'\u092f' Lo
u'\u0928' Lo u'\u094b' Mc

特别是,两行 - 您在output.txt中看到的行 - 以u'\ufeff'开头:

ud.name(u'\ufeff') == 'ZERO WIDTH NO-BREAK SPACE'

这也称为字节顺序标记(BOM),有时在文件的开头用于标识编码。在这里,它可能在编辑时偶然被包含在文件中。如果字符位于文件的最开头,Python似乎会删除该字符,但是当它出现在文件的其他位置时则不会。 strip()显然也不足以将其删除。应手动从输入文件中删除这些字符。

我也在输出中得到以u'\u094b' DEVANAGARI VOWEL SIGN O )结尾的那些,所以我的Python副本显然不会将它们视为字母数字字符。

此外,通常,当您想要匹配正则表达式中的确切字符串时,在将其插入正则表达式之前应使用re.escape(string),以防该字符串包含将被视为正则表达式元字符的字符。