我正在使用Python 2.7.5并尝试获取现有的CSV文件并对其进行处理以删除大于3个字节的unicode字符。 (发送给机械土耳其人,这是亚马逊的限制。)
我试图在这个问题(How to filter (or replace) unicode characters that would take more than 3 bytes in UTF-8?)中使用顶级(惊人)答案。我假设我可以逐行遍历csv,无论我在哪里发现> 3字节的unicode字符,都用替换字符替换它们。
# -*- coding: utf-8 -*-
import csv
import re
re_pattern = re.compile(u'[^\u0000-\uD7FF\uE000-\uFFFF]', re.UNICODE)
ifile = open('sourcefile.csv', 'rU')
reader = csv.reader(ifile, dialect=csv.excel_tab)
ofile = open('outputfile.csv', 'wb')
writer = csv.writer(ofile, delimiter=',', quotechar='"', quoting=csv.QUOTE_ALL)
#skip header row
next(reader, None)
for row in reader:
writer.writerow([re_pattern.sub(u'\uFFFD', unicode(c).encode('utf8')) for c in row])
ifile.close()
ofile.close()
我目前收到此错误:
UnicodeDecodeError: 'ascii' codec can't decode byte 0xea in position 264: ordinal not in range(128)
所以这会在某些行中正确迭代,但在到达奇怪的unicode字符时会停止。
我真的很感激一些指示;我完全糊涂了。我已经取代了#ut; utf8'与' latin1'和unicode(c)。编码到unicode(c).decode并且我一直得到同样的错误。
答案 0 :(得分:3)
您的输入仍然是编码数据,而不是Unicode值。您需要首先解码到unicode
值,但您没有指定要使用的编码。然后,您需要编码再次返回编码值以写回输出CSV:
writer.writerow([re_pattern.sub(u'\uFFFD', unicode(c, 'utf8')).encode('utf8')
for c in row])
您的错误源自unicode(c)
电话;如果没有明确的编解码器,Python将回退到默认的ASCII编解码器。
如果您将文件对象用作上下文管理器,则无需手动关闭它们:
import csv
import re
re_pattern = re.compile(u'[^\u0000-\uD7FF\uE000-\uFFFF]', re.UNICODE)
def limit_to_BMP(value, patt=re_pattern):
return patt.sub(u'\uFFFD', unicode(value, 'utf8')).encode('utf8')
with open('sourcefile.csv', 'rU') as ifile, open('outputfile.csv', 'wb') as ofile:
reader = csv.reader(ifile, dialect=csv.excel_tab)
writer = csv.writer(ofile, delimiter=',', quotechar='"', quoting=csv.QUOTE_ALL)
next(reader, None) # header is not added to output file
writer.writerows(map(limit_to_BMP, row) for row in reader)
我也将替换操作移动到一个单独的函数,并使用生成器表达式按需生成writer.writerows()
函数的所有行。