Scrapy中在parse函数内写入单个文件是否线程安全?内容会混合吗?
问题解答
是的,bigfile.txt完全有可能出现不同HTML页面内容相互混合的情况。
原因:Scrapy默认以多线程(异步)模式处理请求,多个parse方法会被并发执行。而你直接在parse中对同一个文件对象执行write操作,文件写入并非线程安全——当多个线程同时写文件时,A线程的内容还未写完,B线程的写操作就会插入进来,最终导致不同页面的HTML代码被截断、穿插混杂。
修复方案
- 添加线程锁:在爬虫类中初始化线程锁,保证同一时间只有一个线程执行文件写入操作:
import threading def __init__(self): self.time = time_utils.get_current_time_hr() self.folder = f"{ROOT_DIR}/data/tickers/scrapy/{self.time}/" os.makedirs(self.folder, exist_ok=True) filename = self.folder + "bigfile.txt" self.f = open(filename, 'w') self.lock = threading.Lock() # 初始化线程锁 def parse(self, response): html_content = response.body.decode("utf-8") with self.lock: # 自动获取、释放锁,确保写入原子性 self.f.write(html_content) self.f.flush()
- 统一收集后写入:先将所有页面内容存入线程安全的队列,待爬虫结束后一次性写入文件,可通过
closed方法实现:
from queue import Queue def __init__(self): self.time = time_utils.get_current_time_hr() self.folder = f"{ROOT_DIR}/data/tickers/scrapy/{self.time}/" os.makedirs(self.folder, exist_ok=True) self.content_queue = Queue() # 线程安全队列 def parse(self, response): html_content = response.body.decode("utf-8") self.content_queue.put(html_content) def closed(self, reason): filename = self.folder + "bigfile.txt" with open(filename, 'w') as f: while not self.content_queue.empty(): f.write(self.content_queue.get())
内容的提问来源于stack exchange,提问作者dotan
相关产品推荐
相关产品推荐

