scrapy爬蟲管道:持久化存儲(chǔ)文件寫入失敗問題排查
本文分析一個(gè)Scrapy爬蟲項(xiàng)目中,管道(Pipeline)持久化存儲(chǔ)文件寫入失敗的問題。問題表現(xiàn)為:創(chuàng)建的文件為空,無法寫入數(shù)據(jù)。
代碼示例(問題代碼):
# spider.py import scrapy import sys sys.path.append(r'd:project_testpydemodemo1xunlianmyspiderqiubai') from ..items import qiubaiitem class biedouspider(scrapy.Spider): name = "biedou" start_urls = ["https://www.biedoul.com/wenzi/"] def parse(self, response): dl_list = response.xpath('/html/body/div[4]/div[1]/div[1]/dl') for dl in dl_list: title = dl.xpath('./span/dd/a/strong/text()')[0].extract() content = dl.xpath('./dd//text()').extract() content = ''.join(content) item = qiubaiitem() item['title'] = title item['content'] = content yield item break # items.py import scrapy class qiubaiitem(scrapy.Item): title = scrapy.Field() content = scrapy.Field() # pipelines.py class qiubaipipeline(Object): def __init__(self): self.fp = None def open_spdier(self, spider): # 拼寫錯(cuò)誤! print("開始爬蟲") self.fp = open('./biedou.txt', 'w', encoding='utf-8') def close_spider(self, spider): print("結(jié)束爬蟲") self.fp.close() def process_item(self, item, spider): title = str(item['title']) content = str(item['content']) self.fp.write(title + ':' + content + 'n') return item
錯(cuò)誤信息:
... typeerror: object of type qiubaiitem is not json serializable 結(jié)束爬蟲 ... Attributeerror: 'nonetype' object has no attribute 'close'
問題分析:
錯(cuò)誤信息提示’nonetype’ object has no attribute ‘close’,表明self.fp為None,導(dǎo)致無法關(guān)閉文件。 進(jìn)一步追溯原因,發(fā)現(xiàn)pipelines.py文件中open_spdier方法名拼寫錯(cuò)誤,應(yīng)為open_spider。 由于方法名錯(cuò)誤,Scrapy框架無法正確調(diào)用open_spider方法打開文件,導(dǎo)致self.fp始終為None。 TypeError錯(cuò)誤則是因?yàn)閜rocess_item方法嘗試寫入qiubaiitem對(duì)象,而該對(duì)象并非直接可寫入字符串類型。
解決方案:
修正pipelines.py文件中open_spdier方法的拼寫錯(cuò)誤,并改進(jìn)process_item方法以正確處理Item對(duì)象:
# pipelines.py (修正后的代碼) class QiubaiPipeline(object): def __init__(self): self.fp = None def open_spider(self, spider): # 修正拼寫錯(cuò)誤 print("開始爬蟲") self.fp = open('./biedou.txt', 'w', encoding='utf-8') def close_spider(self, spider): print("結(jié)束爬蟲") self.fp.close() def process_item(self, item, spider): title = item['title'] content = item['content'] self.fp.write(f"{title}:{content}n") # 使用f-String更簡潔 return item
通過修正方法名和改進(jìn)process_item方法,確保文件被正確打開和寫入數(shù)據(jù),從而解決文件寫入失敗的問題。 建議使用f-string格式化字符串,代碼更簡潔易讀。 此外,為了更好的錯(cuò)誤處理,建議添加try…except塊來處理潛在的IO錯(cuò)誤。