最近学scrapy爬虫的时候,用CsvItemExporter将Item写入csv文件时,报错
TypeError: write() argument must be str, not bytes
代码如下:
class StockPipelineCSV(object):
def open_spider(self,spider):
self.file = open('stocks_01.csv', 'w')
self.exporter = CsvItemExporter(self.file)
self.exporter.start_exporting()
def close_spider(self,spider):
self.exporter.finish_exporting()
self.file.close()
def process_item(self, item, spider):
self.exporter.export_item(item)
return item
然后找到exporters的CsvItemExporter类中的export_item()函数以及其他相关函数:
#exporters.py
def export_item(self, item):
if self._headers_not_written:
self._headers_not_written = False
self._write_headers_and_set_fields_to_export(item)
fields = self._get_serialized_fields(item, default_value='',
include_empty=True)
values = list(self._build_row(x for _, x in fields))
self.csv_writer.writerow(values)
def _build_row(self, values):
for s in values:
try:
yield to_native_str(s, self.encoding)
except TypeError:
yield s
#python.py
def to_native_str(text, encoding=None, errors='strict'):
""" Return str representation of `text`
(bytes in Python 2.x and unicode in Python 3.x). """
if six.PY2:
return to_bytes(text, encoding, errors)
else:
return to_unicode(text, encoding, errors)
发现这里没问题已经将item转换成存放str对象的一个list了,不知道问题究竟出在哪里?scrapy是初学,不知道是不是scrapy的itempipeline.py代码的问题?
网上查了半天说是要用w+b二进制方式打开,这样确实不会报错了,但写进去之后是乱码,顺序也随机(这个可能是我settings.py里没有设置)
然后我自己写了小程序测试,自己open一个csv文件,以w+b打开
# coding: utf-8
import csv
csvfile = open('D://t.csv', 'w+b')
writer = csv.writer(csvfile)
writer.writerow([str.encode('列1'), str.encode('列2'), str.encode('列3')])
data = [
str.encode('值1'), str.encode('值2'), str.encode('值3')
]
writer.writerow(data)
csvfile.close()
结果报错:
TypeError: a bytes-like object is required, not 'str'
但我明明把他转换成bytes了啊。最后换了一种方式,去掉str.encode(),用w方式写入,正常了。但对bytes-like object和str者二者很困惑,不理解之前的方式为什么会报错。