Странные символы в экспортированных CSV-файлах при конвертации - PullRequest
1 голос
/ 14 марта 2010

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

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

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

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

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

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

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

            # 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
਍㈀  㐀ⴀ 㜀ⴀ㄀㠀 ⴀ ㈀  㐀ⴀ 㜀ⴀ㈀㐀ऀ㘀㈀ഀഀ

Ответы [ 3 ]

3 голосов
/ 14 марта 2010

Проблема заключается в кодировке символов, возможно, в сочетании с универсальной поддержкой 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.

3 голосов
/ 14 марта 2010

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 (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.

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

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

Предлагаемое прочтение: Python Unicode HOWTO и это произведение Джоэля .

2 голосов
/ 14 марта 2010

Нашли решение:

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

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

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

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"

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...