You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 20:52:39