使用Python识别垃圾Unicode字符串

3

我的脚本从csv文件中读取数据,这个csv文件可以有多个包含英文或非英文单词的字符串。

有时文本文件会有垃圾字符串,我想要识别这些字符串并跳过这些字符串,只处理其他字符串。

doc = codecs.open(input_text_file, "rb",'utf_8_sig')
fob = csv.DictReader(doc)
for row, entry in enumerate(f):
    if is_valid_unicode_str(row['Name']):
         process_futher

def is_valid_unicode_str(value):
     try:
         function
         return True
     except UnicodeEncodeError:
         return false

CSV输入:

"Name"
"袋è¢âdcx€¹Ã¤Â¸Å½Ã¦Å“‹å‹们çâ€ÂµÃ¥Â­Âå•â€"
"元大寶來證券"
"John Dove"

我希望您能够翻译函数is_valid_unicode_str(),该函数将识别垃圾字符串并仅处理有效的字符串。
我尝试使用decode来解码垃圾字符串,但是失败了。
value.decode('utf8')

预期输出是需要处理的中英文字符串。 请问如何实现筛选有效Unicode文件的功能?

3
你的文件中出现了乱码字符串,这是由于数据在某个时刻被编码成一种格式,然后解码成另一种格式所导致的。由于你的文件已经被统一编码为UTF-8,因此codecs.open()已经将其解码为Unicode字符串。 - Martijn Pieters
1
有可能 Mojibake 可以被“修复”,而不是被丢弃。看看 ftfy 能做些什么来理解你所拥有的字符串。 - Martijn Pieters
到目前为止,我可以从你的乱码中获得 猫垄姑⑩dcx盲赂沤忙姑ヂ姑ぢ宦р得ヂ氓⑩猫垄鈥姑⑩dcx盲赂沤忙艙鈥姑ヂ鈥姑ぢ宦р得ヂ氓鈥⑩猫垄鈥姑⑩dcx盲赂沤忙艙鈥姑ヂ鈥姑ぢ宦р得ヂ氓鈥⑩(GB2312、GBK和GB18030)。我会进一步查看。 - Martijn Pieters
很遗憾,FTFY不支持GB*系列编解码器;我已经在项目中提交了一个探索性问题。 - Martijn Pieters
在未来的帖子中,您能否包括 print repr(broken_value) 的输出?这样,任何不可打印和非 ASCII 字节将被包含为转义序列,使我们能够准确地重新创建该值。 - Martijn Pieters
显示剩余2条评论
2个回答

8

(这里是ftfy开发者)

我猜测这段文本可能是“袋袋与朋友们电子商”。由于你提供的字符串中缺少一些字符,我不得不猜测“友”,“子”和“商”的汉字。在猜测时,我选择了最常见的字符。我不知道“dcx”应该放在哪里或为什么会出现。

谷歌翻译在这里并不是很有用,但似乎意思是关于电子商务的。

所以这就是你的文本经历的所有问题:

  1. 它被编码为UTF-8,但被错误地解码为sloppy-windows-1252,两次
  2. 在UTF-8序列的中间插入了字母“dcx”
  3. 去除了在windows-1252中不存在的字符--具有字节值81、8d、8f、90和9d
  4. 从末尾删除了一个不间断空格(字节值a0)

如果只有第一个问题发生了,ftfy.fix_text_encoding将能够修复它。剩下的问题可能只是在你尝试将字符串放到Stack Overflow上时发生的。

所以这是我的建议:

  • 找出谁一直将数据错误地解码为sloppy-windows-1252,并让他们改为正确的UTF-8解码。
  • 如果你再次遇到这样的字符串,请尝试使用ftfy.fix_text_encoding进行修复。

3

您遇到了乱码字符串问题;文本使用一种编码方式进行编码,但是却使用另一种编码方式进行解码。

在这种情况下,您的文本使用Windows 1252代码页进行解码;文本中的U+20AC欧元符号是CP1252 Mojibakes的典型特征。原始编码可能是GB*系列的中文编码之一,或者是多次往返的UTF-8 - CP1252 Mojibake。我无法确定其中哪一个,因为我不能读取中文,也没有您的完整数据;CP1252 Mojibakes包括不可打印字符,如0x81和0x8D字节,这些字符可能在您发布问题时丢失了。

我会安装ftfy项目;它不能修复GB*编码(我请求该项目添加支持),但它包括一个名为sloppy-windows-1252的新编解码器,可以让您使用该编解码器逆转错误解码:
>>> import ftfy  # registers extra codecs on import
>>> text = u'袋è¢âdcx€¹Ã¤Â¸Å½Ã¦Å“‹å‹们çâ€ÂµÃ¥Â­Âå•â€'
>>> print text.encode('sloppy-windows-1252').decode('gb2312', 'replace')
猫垄�姑�⑩dcx�盲赂沤忙��姑ヂ�姑ぢ宦�р�得ヂ�氓�⑩�
>>> print text.encode('sloppy-windows-1252').decode('gbk', 'replace')
猫垄鈥姑�⑩dcx�盲赂沤忙艙鈥姑ヂ鈥姑ぢ宦�р�得ヂ�氓鈥⑩�
>>> print text.encode('sloppy-windows-1252').decode('gb18030', 'replace')
猫垄鈥姑⑩dcx�盲赂沤忙艙鈥姑ヂ鈥姑ぢ宦р�得ヂ氓鈥⑩�
>>> print text.encode('sloppy-windows-1252').decode('utf8', 'ignore').encode('sloppy-windows-1252').decode('utf8', 'replace')
袋�dcx与朋�们���

U+FFFD REPLACEMENT CHARACTER 表示解码并不完全成功,但这可能是由于您复制的字符串中缺少任何不可打印或使用0x81或0x8D字节的内容造成的。

您可以尝试使用以下方式修复数据:从文件数据开始,先编码为sloppy-windows-1252,然后解码为GB *编解码之一,或者进行两次UTF-8往返并查看哪个最合适。

如果这还不够好(您无法修复数据),则可以使用ftfy.badness.sequence_weirdness()函数来尝试检测问题:

>>> from ftfy.badness import sequence_weirdness
>>> sequence_weirdness(text)
9
>>> sequence_weirdness(u'元大寶來證券')
0
>>> sequence_weirdness(u'John Dove')
0

Mojibakes在“序列奇异性”尺度上得分很高。你可以尝试找到一个适当的阈值来确定哪些数据最可能已经损坏了。
然而,我认为我们可以使用非零返回值作为另一个测试的起点。英文文本应该在该尺度上得分为0,中文文本也应该是如此。混合中英文的文本仍然可以得分超过0,但是你无法将那些中文文本编码为CP-1252编解码,而你可以对损坏的文本进行编码。
from ftfy.badness import sequence_weirdness

def is_valid_unicode_str(text):
    if not sequence_weirdness(text):
        # nothing weird, should be okay
        return True
    try:
        text.encode('sloppy-windows-1252')
    except UnicodeEncodeError:
        # Not CP-1252 encodable, probably fine
        return True
    else:
        # Encodable as CP-1252, Mojibake alert level high
        return False

@Shashi:所以你大概是用“编码为杂乱的cp1252,然后解码”的方法解决了这个问题? - Martijn Pieters

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接