Странные символы в экспортированных CSV-файлах при конвертации

1

Я столкнулся с проблемой, которую я не могу решить самостоятельно, относительно загружаемых файлов данных трендов в формате csv из Google Insights for Search.

Я должен лениться, чтобы переформатировать файлы, которые I4S дает мне вручную, что означает: извлечение раздела с данными фактических тенденций и переформатирование столбцов, чтобы я мог использовать его с программой моделирования, которую я делаю для школы.

Итак, я написал крошечный script, должен сделать для меня работу: взять файл, сделать магию и дать мне новый файл в правильном формате.

То, что он должен делать, - это прочитать содержимое файла, извлечь раздел трендов, разделить его на новые строки, разделить каждую строку, а затем изменить порядок столбцов и, возможно, переформатировать их.

При взгляде на нетронутый файл csv I4S он выглядит нормальным, содержащим CR LF-символы при разрыве строк (возможно, только потому, что я использую Windows).

Когда только чтение содержимого, а затем запись их в новый файл с использованием script wierd asian символов появляются между CR и LF. Я попробовал script с написанным вручную подобным образом выглядящим файлом и даже попробовал csv файл из Google Trends, и он отлично работает.

Я использую Python и script (фрагмент), который я использовал для следующего примера выглядит следующим образом:

            # Read from an input file 
            file = open(file,"r") 
            contents = file.read() 
            file.close() 
            cfile = open("m.log","w+") 
            cfile.write(contents) 
            cfile.close()

Есть ли у кого-нибудь идея, почему эти персонажи появляются? Спасибо, что помогли!

Я приведу вам и пример:

Первые несколько строк файла csv I4S:

Web Search Interest: foobar
Worldwide; 2004 - present

Interest over time
Week foobar
2004-01-04 - 2004-01-10 44
2004-01-11 - 2004-01-17 44
2004-01-18 - 2004-01-24 37
2004-01-25 - 2004-01-31 40
2004-02-01 - 2004-02-07 49
2004-02-08 - 2004-02-14 51
2004-02-15 - 2004-02-21 45
2004-02-22 - 2004-02-28 61
2004-02-29 - 2004-03-06 51
2004-03-07 - 2004-03-13 48
2004-03-14 - 2004-03-20 50
2004-03-21 - 2004-03-27 56
2004-03-28 - 2004-04-03 59

Выходной файл при чтении и записи содержимого:

Web Search Interest: foobar
਍圀漀爀氀搀眀椀搀攀㬀 ㈀  㐀 ⴀ 瀀爀攀猀攀渀琀ഀഀ

਍䤀渀琀攀爀攀猀琀 漀瘀攀爀 琀椀洀攀ഀഀ
Week foobar
਍㈀  㐀ⴀ ㄀ⴀ 㐀 ⴀ ㈀  㐀ⴀ ㄀ⴀ㄀ ऀ㐀㐀ഀഀ
2004-01-11 - 2004-01-17 44
਍㈀  㐀ⴀ ㄀ⴀ㄀㠀 ⴀ ㈀  㐀ⴀ ㄀ⴀ㈀㐀ऀ㌀㜀ഀഀ
2004-01-25 - 2004-01-31 40
਍㈀  㐀ⴀ ㈀ⴀ ㄀ ⴀ ㈀  㐀ⴀ ㈀ⴀ 㜀ऀ㐀㤀ഀഀ
2004-02-08 - 2004-02-14 51
਍㈀  㐀ⴀ ㈀ⴀ㄀㔀 ⴀ ㈀  㐀ⴀ ㈀ⴀ㈀㄀ऀ㐀㔀ഀഀ
2004-02-22 - 2004-02-28 61
਍㈀  㐀ⴀ ㈀ⴀ㈀㤀 ⴀ ㈀  㐀ⴀ ㌀ⴀ 㘀ऀ㔀㄀ഀഀ
2004-03-07 - 2004-03-13 48
਍㈀  㐀ⴀ ㌀ⴀ㄀㐀 ⴀ ㈀  㐀ⴀ ㌀ⴀ㈀ ऀ㔀 ഀഀ
2004-03-21 - 2004-03-27 56
਍㈀  㐀ⴀ ㌀ⴀ㈀㠀 ⴀ ㈀  㐀ⴀ 㐀ⴀ ㌀ऀ㔀㤀ഀഀ
2004-04-04 - 2004-04-10 69
਍㈀  㐀ⴀ 㐀ⴀ㄀㄀ ⴀ ㈀  㐀ⴀ 㐀ⴀ㄀㜀ऀ㘀㔀ഀഀ
2004-04-18 - 2004-04-24 51
਍㈀  㐀ⴀ 㐀ⴀ㈀㔀 ⴀ ㈀  㐀ⴀ 㔀ⴀ ㄀ऀ㔀㄀ഀഀ
2004-05-02 - 2004-05-08 56
਍㈀  㐀ⴀ 㔀ⴀ 㤀 ⴀ ㈀  㐀ⴀ 㔀ⴀ㄀㔀ऀ㔀㈀ഀഀ
2004-05-16 - 2004-05-22 54
਍㈀  㐀ⴀ 㔀ⴀ㈀㌀ ⴀ ㈀  㐀ⴀ 㔀ⴀ㈀㤀ऀ㔀㔀ഀഀ
2004-05-30 - 2004-06-05 74
਍㈀  㐀ⴀ 㘀ⴀ 㘀 ⴀ ㈀  㐀ⴀ 㘀ⴀ㄀㈀ऀ㔀㜀ഀഀ
2004-06-13 - 2004-06-19 50
਍㈀  㐀ⴀ 㘀ⴀ㈀  ⴀ ㈀  㐀ⴀ 㘀ⴀ㈀㘀ऀ㔀㐀ഀഀ
2004-06-27 - 2004-07-03 58
਍㈀  㐀ⴀ 㜀ⴀ 㐀 ⴀ ㈀  㐀ⴀ 㜀ⴀ㄀ ऀ㔀㤀ഀഀ
2004-07-11 - 2004-07-17 59
਍㈀  㐀ⴀ 㜀ⴀ㄀㠀 ⴀ ㈀  㐀ⴀ 㜀ⴀ㈀㐀ऀ㘀㈀ഀഀ

  • 0
    У меня нет проблем с запуском вашего скрипта во входном файле, поэтому либо что-то очень странное в вашей системе, либо вы на самом деле не запускаете скрипт, который вы здесь поместили. Эти файлы входят в UTF-8, но, если вы буквально записываете те же самые байты, которые читали, это действительно не должно иметь никакого значения для вас.
  • 0
    Я думаю, что входной файл может быть более сложным, чем вы думаете: может ли его открыть блокнот?
Показать ещё 3 комментария
Теги:
csv

3 ответа

3
Лучший ответ

repr() - ваш друг (кроме Python 3.X; вместо этого используйте ascii()).

prompt>\python26\python -c "print repr(open('report.csv','rb').read()[:300])"
'\xff\xfeW\x00e\x00b\x00 \x00S\x00e\x00a\x00r\x00c\x00h\x00 \x00I\x00n\x00t\x00e
\x00r\x00e\x00s\x00t\x00:\x00 \x00f\x00o\x00o\x00b\x00a\x00r\x00\r\x00\n\x00W\x0
[snip]
x001\x007\x00\t\x004\x004\x00\r\x00\n\x002\x000\x00'

Уверен, что выглядит как UTF-16LE BOM (U + FEFF) в первых двух байтах.

Блокнот. * НЕ являются твоими друзьями. UTF-16 не следует называть "UCS-2" или "Unicode".

Следующее должно помочь в следующем:

>>> import codecs
>>> lines = list(codecs.open('report.csv', 'r', encoding='UTF-16'))
>>> import pprint
>>> pprint.pprint(lines[:8])
[u'Web Search Interest: foobar\r\n',
 u'Worldwide; 2004 - present\r\n',
 u'\r\n',
 u'Interest over time\r\n',
 u'Week\tfoobar\r\n',
 u'2004-01-04 - 2004-01-10\t44\r\n',
 u'2004-01-11 - 2004-01-17\t44\r\n',
 u'2004-01-18 - 2004-01-24\t37\r\n']
>>>

Обновление: Почему ваш выходной файл выглядит как gobbledegook.

Во-первых, вы просматриваете файлы с чем-то (Notepad. * возможно), который знает, что файлы якобы закодированы в UTF-16LE и отображает их соответственно. Таким образом, ваш входной файл выглядит нормально.

Однако ваш script читает входной файл как необработанные байты. Затем он записывает выходной файл как сырые байты в текстовом режиме ('w') (в отличие от двоичного режима ('wb')). Поскольку вы находитесь в Windows, каждый \n будет заменен на \r\n. Это добавляет один байт (HALF символа UTF-16) в каждую строку. Таким образом, каждая строка SECOND будет бассой, как UTF-16BE... буква A, которая является \x41\x00 в UTF-16LE, потеряет свой конечный \x00 и возьмет старший байт (возможно,\x00) от символа влево, \x00\x41 - это UTF-16LE для символа CJK ( "Азиатский" ).

Рекомендуемое чтение: Python Unicode HOWTO и этот фрагмент Joel.

  • 0
    Спасибо за ответ ... да, вы правы ... работа с кодировками всегда была чем-то загадочным, поэтому спасибо за предложенные вами статьи! Я читаю их.
  • 0
    Спасибо за спасибо ... но попробуйте кнопку голосования :-)
Показать ещё 1 комментарий
3

Проблема заключается в кодировании символов, возможно, в сочетании с универсальной поддержкой конца строки Python. Как вы уже упоминали, исходный файл находится в UCS-2 LE с отметкой байтового заказа (BOM). Вам нужно сделать что-то вроде:

import codecs

input_file = codecs.open("Downloads/report.csv", "r", encoding="utf_16")
contents = input_file.read() 
input_file.close() 

cfile = codecs.open("m.log", "w+", encoding="utf_8")
cfile.write(contents) 
cfile.close()

Это будет читать входной файл, правильно декодировать его и записать в новый файл как UTF-8. Вам нужно будет удалить существующий файл m.log.

  • 0
    Как упомянуто Джоном. UCS-2 - это старый термин, UTF-16 - правильное имя.
2

Найдено решение:

Это была проблема кодирования символов. В зависимости от редактора вы используете другие кодировки набора символов:

Блокнот ++: ucs-2 little endian PSPad: utf-16le

Расшифровка содержимого с помощью ucs-2 не работала, поэтому я попробовал utf-16le, и все прошло хорошо. extraneons ответ был неправильным, но он привел меня к сайту, где я узнал, что использование "U" в методе открытия файла вызывает распознавание "\ r\n" как разрывов строк. Итак, теперь соответствующий фрагмент моего script выглядит следующим образом:

file = open(file,'rU')
contents = file.read()
file.close()

contents = contents.decode("utf-16le").encode("utf-8")

Затем я кодирую содержимое с помощью utf-8 и удаляю все пустые строки с помощью

lines = contents.split("\n")
contents = ""
for line in lines:
  if not line.strip():
    continue
  else:
    contents += line+"\n"

Теперь я могу продолжить разделение и переформатирование файла. Спасибо Нику Бастину, ты дал мне подсказку, в которой я нуждался!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню