我使用Python2.7.3和BeuatofulSoup从网站的表中获取数据,然后使用codecs将内容写入文件。我收集的变量之一,偶尔会混淆其中的字符。例如,如果网站表如下所示
Year Name City State
2000 John D’Iberville MS
2001 Steve Arlington VA因此,当我生成我的City变量时,我总是将它编码为utf-8
Year = foo.text
Name = foo1.text
City = foo3.text.encode('utf-8').strip()
State = foo4.text
RowsData = ("{0},{1},{2},{3}").format(Year, Name, City, State)因此,我创建的一个名为RowData和RowHeaders的逗号分隔字符串列表的内容如下所示
RowHeaders = ['Year,Name,City,State']
RowsData = ['2000, John, D\xc3\xa2\xe2\x82\xac\xe2\x84\xa2Iberville, MS',
'2001, Steve, Arlington, VA']然后,我尝试使用以下代码将其写入文件
file1 = codecs.open(Outfile.csv,"wb","utf8")
file1.write(RowHeaders + u'\n')
line = "\n".join(RowsData)
file1.write(line + u'\r\n')
file1.close()我得到以下错误
Traceback (most recent call last):
File "HSRecruitsFBByPosition.py", line 141, in <module>
file1.write(line + u'\r\n')
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 6879: ordinal not in range(128)我可以在RowsData上使用csv编写程序包,它工作得很好。由于我不想进入的原因,我需要使用编解码器输出csv文件。我搞不懂到底是怎么回事。有人能帮我解决这个问题吗?提前谢谢。
发布于 2014-08-20 07:27:09
codecs.open() 为您编码。不要把编码过的数据交给它,因为会尝试并再次为您解码数据,这样它就可以将其编码到UTF-8。该隐式解码使用ASCII编解码器,但由于编码字节字符串中有非ASCII数据,因此失败:
>>> u'D’Iberville'.encode('utf8')
'D\xc3\xa2\xe2\x82\xac\xe2\x84\xa2Iberville'
>>> u'D’Iberville'.encode('utf8').encode('utf8')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 1: ordinal not in range(128)解决方案是*不手动编码:
Year = foo.text
Name = foo1.text
City = foo3.text.strip()
State = foo4.text注意,codecs.open()不是文件流最有效的实现。在Python2.7中,我使用相反,;它提供了相同的功能,但实现起来更加健壮。io模块是Python3的默认I/O实现,但也可以在Python2中实现前向兼容性。
但是,您似乎在重新发明CSV处理;Python有一个优秀的模块,可以为您生成CSV文件。但是,在Python 2中,它不能处理Unicode,因此您确实需要手动编码:
import csv
# ...
year = foo.text
name = foo1.text
city = foo3.text.strip()
state = foo4.text
row = [year, name, city, state]
with open(Outfile.csv, "wb") as outf:
writer = csv.writer(outf)
writer.writerow(['Year', 'Name', 'City', 'State'])
writer.writerow([c.encode('utf8') for c in row])最后但并非最不重要的一点是,如果您的HTML页面生成了文本D’Iberville,那么您就产生了一个莫吉贝克;在这个莫吉贝克中,您将UTF-8误解为CP-1252:
>>> u'D’Iberville'.encode('cp1252').decode('utf8')
u'D\u2019Iberville'
>>> print u'D’Iberville'.encode('cp1252').decode('utf8')
D’Iberville这通常是由于绕过BeautifulSoup的编码检测(传入字节字符串而不是Unicode)造成的。
你可以试着在事实发生后用以下方法“修复”这些:
try:
City = City.encode('cp1252').decode('utf8')
except UnicodeError:
# Not a value that could be de-mojibaked, so probably
# not a Mojibake in the first place.
pass发布于 2014-08-20 07:36:06
这个'D\xc3\xa2\xe2\x82\xac\xe2\x84\xa2Iberville'是一个普通的字符串,它恰好有表示字符的转义位。
所以,要把它写出来,首先要对它进行解码。由于您还没有给出解码,Python正在尝试ASCII,但失败了。
>>> s
'D\xc3\xa2\xe2\x82\xac\xe2\x84\xa2Iberville'
>>> type(s)
<type 'str'>
>>> type(s.decode('utf-8'))
<type 'unicode'>
>>> print(s.decode('utf-8'))
D’Iberville下面是如何理解这个过程:
https://stackoverflow.com/questions/25398976
复制相似问题