8

所以我试图将 JSON 文件解析成一个制表符分隔的文件。解析似乎工作正常,所有数据都通过了。尽管输出文件上发生了最奇怪的事情。我告诉它使用制表符分隔符并在输出中使用制表符,但它似乎仍然保留单引号。出于某种原因,它似乎也在开头添加了字母 B。我手动输入了标题,效果很好,但数据本身表现得很奇怪。这是我得到的输出示例。

id  created text    screen name name    latitude    longitude   place name  place type
b'1234567890'   b'Thu Mar 14 19:39:07 +0000 2013'   "b""I'm at Bank Of America (Wayne, MI) http://t.co/asdf"""  b'userid'   b'username' 42.28286837 -83.38487864    b'Bank Of America, Wayne'   b'poi'
b'1234567891'   b'Thu Mar 14 19:39:16 +0000 2013'   b'here is a sample tweet \xf0\x9f\x8f\x80 #notingoodhands'  b'userid2'  b'username2'

这是我用来写出数据的代码。

out = open(filename, 'w')
   out.write('id\tcreated\ttext\tscreen name\tname\tlatitude\tlongitude\tplace name\tplace type')
   out.write('\n')
   rows = zip(ids, times, texts, screen_names, names, lats, lons, place_names, place_types)
   from csv import writer
   csv = writer(out, dialect='excel', delimiter = '\t')
   for row in rows:
       values = [(value.encode('utf-8') if hasattr(value, 'encode') else value) for value in row]
       csv.writerow(values)
   out.close()

事情就是这样。如果我在没有 utf-8 位的情况下执行此操作并直接输出,那么格式将完全符合我的要求。但是当人们输入特殊字符时,程序会崩溃并且无法处理。

Traceback (most recent call last):
  File "tweets.py", line 34, in <module>
    csv.writerow(values)
  File "C:\Python33\lib\encodings\cp1252.py", line 19, in encode
    return codecs.charmap_encode(input,self.errors,encoding_table)[0]
UnicodeEncodeError: 'charmap' codec can't encode character '\U0001f3c0' in position 153: character maps to <undefined>

添加 utf-8 位会将其转换为您在此处看到的输出类型,但随后会将所有这些字符添加到输出中。有人对此有任何想法吗?

4

2 回答 2

13

您正在将字节数据而不是 unicode 写入文件,因为您自己对数据进行编码。

完全删除encode调用,让 Python 为您处理;使用 UTF8 编码打开文件,其余部分自行处理:

out = open(filename, 'w', encoding='utf8')

这记录在csv模块文档中:

由于open()用于打开 CSV 文件进行读取,默认情况下该文件将使用系统默认编码解码为 un​​icode(请参阅 参考资料locale.getpreferredencoding())。要使用不同的编码解码文件,请使用 open 的 encoding 参数:

import csv
with open('some.csv', newline='', encoding='utf-8') as f:
    reader = csv.reader(f)
    for row in reader:
         print(row)

这同样适用于以系统默认编码以外的方式写入:打开输出文件时指定编码参数。

于 2013-03-14T21:25:16.397 回答
1

这里有很多事情要做,但首先,让我们澄清一些困惑。

将非 ASCII 字符编码为 UTF-8 意味着您可以获得多个字节。例如,字符\xf0\x9f\x8f\x80UTF-8。但这仍然只是一个字符,它只是一个占用四个字节的字符。如果您将字符串写入二进制文件,然后在 UTF-8 兼容工具(记事本或 TextEdit,或仅cat在 UTF-8 友好终端/shell 上)查看该文件,您会看到一个,而不是四个垃圾字符。

其次,b'abc'不是b添加到开头的字符串,而是reprbyte-string 的表示abc。与引号一样,b它不再是字符串的一部分。

最后,在 Python 3 中,您不能以文本模式打开文件,然后将字节字符串写入其中。要么以文本模式打开它,使用编码,然后写入普通的 unicode 字符串,要么以二进制模式打开它并写入编码的字节字符串。

于 2013-03-14T21:35:30.727 回答