使用Python 3删除“编码大于3个字节的字符”

时间:2018-06-06 22:23:01

标签: python python-3.x unicode byte encode

我想删除编码大于3个字节的字符。 因为当我将我的CSV数据上传到Amazon Mechanical Turk系统时,它会要求我这样做。

  

您的CSV文件需要采用UTF-8编码,且不能包含字符   编码大于3个字节。例如,一些非英语   不允许使用字符(了解更多信息)。

要克服这个问题, 我想创建一个filter_max3bytes函数来删除Python3中的那些字符。

x = 'below ð\x9f~\x83,'
y = remove_max3byes(x)  # y=="below ~,"

然后我将应用该功能,然后将其保存为CSV文件,该文件为UTF-8编码。

This post与我的问题有关,但他们使用的是python 2,解决方案对我没用。

谢谢!

3 个答案:

答案 0 :(得分:1)

字符串中的所有字符似乎都不是UTF-8中的3个字节:

x = 'below ð\x9f~\x83,'

无论如何,删除它们的方法,如果有的话:

filtered_x = ''.join(char for char in x if len(char.encode('utf-8')) < 3)

例如(带有这样的字符):

>>> x = 'abcd漢字efg'
>>> ''.join(char for char in x if len(char.encode('utf-8')) < 3)
'abcdefg'

顺便说一下,您可以通过执行以下操作来验证您的原始字符串是否没有3字节编码:

>>> for char in 'below ð\x9f~\x83,':
...     print(char, [hex(b) for b in char.encode('utf-8')])
...
b ['0x62']
e ['0x65']
l ['0x6c']
o ['0x6f']
w ['0x77']
  ['0x20']
ð ['0xc3', '0xb0']
  ['0xc2', '0x9f']
~ ['0x7e']
  ['0xc2', '0x83']
, ['0x2c']

编辑:疯狂猜测

我认为OP提出错误的问题,问题实际上是该字符是否可打印。我假设Python显示的任何内容都是\x<number>不可打印的,所以这个解决方案应该有效:

x = 'below ð\x9f~\x83,'
filtered_x = ''.join(char for char in x if not repr(char).startswith("'\\x"))

结果:

'below ð~,'

答案 1 :(得分:1)

虽然间接声明,但网站仅允许使用基本多语言平面(BMP)中的字符。这包括Unicode代码点U + 0000到U + FFFF。在UTF-8中,对U + FFFF以上的任何内容进行编码需要四个字节:

>>> '\uffff'.encode('utf8')
b'\xef\xbf\xbf'
>>> '\U00010000'.encode('utf8')
b'\xf0\x90\x80\x80'

这会过滤掉U + FFFF以上的Unicode代码点:

>>> test_string = 'abc马克' # emoticon is U+1F600
>>> ''.join(c for c in test_string if ord(c) < 0x10000)
'abc马克'

编码时(注意每个汉字的三个字节):

>>> ''.join(c for c in test_string if ord(c) < 0x10000).encode('utf8')
b'abc\xe9\xa9\xac\xe5\x85\x8b'

答案 2 :(得分:0)

根据the UTF-8 standard,Unicode代码点低于U + 0800的字符在编码中最多使用两个字节。所以只需删除U + 0800或以上的任何角色。此代码复制最多占用两个字节的所有字符,并忽略其他字符。

def remove_max3byes(x):
    return ''.join(c for c in x if ord(c) < 0x800)

正如评论指出的那样,您的示例字符串没有超过两个字节的字符。但这个命令在REPL

remove_max3byes(chr(0x07ff))

给出

'\u07ff'

和这个命令

remove_max3byes(chr(0x0800))

给出

''

两者都是想要的。