我遇到了一个问题,我无法自行解决Google Insights for Search中可下载的csv格式趋势数据文件。
我懒得重新格式化文件I4S手动给我的意思是:用实际趋势数据提取部分并重新格式化列,以便我可以将它用于我为学校做的建模程序。
所以我写了一个小脚本应该为我做的工作:拿一个文件,做一些魔术并给我一个正确格式的新文件。
它应该做的是读取文件内容,提取趋势部分,按换行分割它们,拆分每一行然后重新排序列并重新格式化它们。
当查看未触及的I4S csv文件时,它看起来很正常,包含换行符时的CR LF字符(也许这只是因为我使用的是Windows)。
当只是阅读内容然后使用脚本将它们写入新文件时,CR和LF之间会出现奇怪的亚洲字符。我尝试使用手动编写的类似文件的脚本,甚至尝试了谷歌趋势的csv文件,它工作正常。
我使用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()
有谁知道为什么这些字符出现???谢谢你的帮助!
我会给你和榜样:
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 :(得分: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。* may),这些文件知道这些文件是以UTF-16LE编码的,并相应地显示它们。所以你的输入文件看起来很好。
但是,您的脚本正在将输入文件作为原始字节读取。然后它以文本模式('w')将输出文件写为原始字节(而不是二进制模式('wb'))。由于您使用的是Windows,因此每个\n
都会被\r\n
替换。这是为每一行添加一个字节(UTF-16字符的HALF)。因此,每条SECOND线都将是低音大战,也就是UTF-16BE ...... UTF-16LE中的字母A是\ x41 \ x00将丢失其尾随的\ x00并从左边的字符中拾取一个前导字节(可能是\ x00) 。 \ x00 \ x41是CJK(“亚洲”)角色的UTF-16LE。
答案 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。
答案 2 :(得分:2)
找到解决方案:
这是一个字符编码问题。根据您使用的编辑器,显示其他字符集编码:
Notepad ++: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"
现在我可以继续拆分并重新格式化文件了。感谢Nick Bastin,你给了我需要的提示!