管道中數(shù)據(jù)保存成json格式,但是文件每一行是獨(dú)立的{} 字典結(jié)構(gòu),整個(gè)文件不是標(biāo)準(zhǔn)的json結(jié)構(gòu)。
需要在每一行的末尾加上','和換行,整個(gè)文件需要用[]包括起來(lái),這樣文件才是標(biāo)準(zhǔn)的json格式。
為此管道文件pipelines.py文件需要這樣寫:
第一種方法:
import codecs
import json
import os
class XxxxprojectPipeline(object):
# 構(gòu)造方法,在調(diào)用類的時(shí)候只執(zhí)行一次
def __init__(self):
super().__init__() # 執(zhí)行父類的構(gòu)造方法
self.fp = codecs.open('scraped_data_utf8.json', 'w', encoding='utf-8')
self.fp.write('[')
# 來(lái)一個(gè)item就會(huì)調(diào)用一次這個(gè)方法
def process_item(self, item, spider):
# 將item轉(zhuǎn)為字典
d = dict(item)
# 將字典轉(zhuǎn)為json格式
string = json.dumps(d, ensure_ascii=False)
self.fp.write(string + ',\n') # 每行數(shù)據(jù)之后加入逗號(hào)和換行
return item
def close_spider(self, spider):
self.fp.seek(-2, os.SEEK_END) # 定位到倒數(shù)第二個(gè)字符,即最后一個(gè)逗號(hào)
self.fp.truncate() # 刪除最后一個(gè)逗號(hào)
self.fp.write(']') # 文件末尾加入一個(gè)‘]’
self.fp.close() # 關(guān)閉文件
第二種方法:
調(diào)用scrapy提供的json export導(dǎo)出json文件,然后在settings.py
from scrapy.exporters import JsonItemExporter
class JsonExporterPipleline(object):
def __init__(self):
self.file = open('xxx.json', 'wb')
self.exporter = JsonItemExporter(self.file, encoding="utf-8", ensure_ascii=False)
self.exporter.start_exporting()
def process_item(self, item, spider):
self.exporter.export_item(item)
return item
def close_spider(self, spider):
self.exporter.finish_exporting()
self.file.close()
然后在settings.py文件中的ITEM_PIPELINES參數(shù)中添加此類
ITEM_PIPELINES = {
'xxxproject.pipelines.JsonExporterPipleline': 30, # 添加管道
}
最后在項(xiàng)目/spiders目錄下運(yùn)行程序
scrapy crawl 爬蟲名
這2種方法都可以獲取完美的json,不同的是,第一種傳入了每行數(shù)據(jù)之后換行,第2種方法默認(rèn)是一行,中間不換行。
如果pipelines.py種同時(shí)寫了這2種方法,并且在settings.py文件中同時(shí)開啟了這2種方法,那么在運(yùn)行程序的時(shí)候會(huì)生成2個(gè)文件名不同,內(nèi)容相同的json文件(如果兩個(gè)方法中寫入的文件名不同的話)
事實(shí)上,我們只需要一個(gè)就行了。2種方法,2選1.