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

如何在单个user-data-dir下使用多进程运行Selenium Chrome实例?

如何在单个user-data-dir下使用多进程运行Selenium Chrome实例?

这个问题我之前折腾过好一阵子!核心原因是Chrome根本不允许多个实例同时共用同一个用户数据目录(user-data-dir)——它会对这个目录加排他锁,防止多个进程同时读写配置、cookie这类数据,所以就会出现你看到的「无法删除旧devtools端口文件」的冲突错误。

下面给你两个可行的解决方案,结合你的代码来改就行:

方案1:给每个进程分配独立的Profile子目录

Chrome的user-data-dir目录本身就支持多个独立的Profile子目录(比如默认的Default,或者你手动创建的Profile 1、Profile 2)。我们可以让所有进程共用同一个主user-data-dir,但给每个进程指定不同的--profile-directory参数,这样既共享了主目录的基础配置和cookie,又不会互相干扰。

具体修改步骤:

  1. 在调用多进程任务时,给每个任务传递一个唯一的Profile标识(比如用循环索引)
  2. 修改浏览器驱动的配置,添加--profile-directory参数

比如修改你的delete_empty_albums函数里的循环部分:

for idx, album in enumerate(tqdm(albums.albums,
        desc = "Deleting empty albums",
        unit = "album",
        position = 0,
        leave = True)):
    if album.mediaItemsCount == 0:
        try:
            tqdm.write(f"{Fore.BLUE}🗑️ Remove the empty album: \"{album.title}\"{Fore.RESET}")
            tqdm.write(f"\tURL: {album.productUrl}{Fore.RESET}")

            # 给每个任务分配唯一的Profile子目录名称
            profile_dir = f"Profile_{idx}"
            pool.apply_async(delete_album,
                args = (album.productUrl, location, profile, profile_dir),
                callback = lambda _: delete_album_success(album.title, album.id),
                error_callback = lambda e: delete_album_error(album.title, album.id, e)
            )
        except Exception as e:
            # ... 原有错误处理代码不变

然后修改delete_album和browser_driver函数,新增profile_dir参数:

def delete_album(album_productUrl: str, location: pathlib.Path, profile: pathlib.Path, profile_dir: str) -> bool:
    driver = browser_driver(location, profile, profile_dir)
    # ... 原有逻辑完全不变

def browser_driver(location: pathlib.Path, profile: pathlib.Path, profile_dir: str) -> webdriver.Chrome:
    options = Options()
    if location:
        options.binary_location = str(location)
    options.headless = True

    # 保留原有的user-data-dir配置
    options.add_argument(f"--user-data-dir={profile}")
    # 添加这一行,指定当前进程使用的独立Profile子目录
    options.add_argument(f"--profile-directory={profile_dir}")

    # ... 原有其他配置不变
    driver = webdriver.Chrome(options = options)
    driver.set_window_size(800, 600)

    return driver

这样每个进程会使用user-data-dir下的不同子目录,完全不会冲突,还能共享主目录的cookie数据。

方案2:给每个实例指定独立的调试端口

有时候即使Profile独立了,devtools的端口也可能出现冲突,我们可以给每个Chrome实例指定唯一的调试端口,进一步避免冲突:

在browser_driver函数里添加端口配置:

import os

def browser_driver(location: pathlib.Path, profile: pathlib.Path, profile_dir: str) -> webdriver.Chrome:
    options = Options()
    # ... 原有配置

    # 生成唯一的调试端口,比如基于进程ID或者索引
    # 这里用进程ID取模,确保端口在9222-9322之间(可自行调整范围)
    port = 9222 + os.getpid() % 100
    options.add_argument(f"--remote-debugging-port={port}")

    # ... 其他配置不变

额外注意事项

  • 启动脚本前一定要关闭所有正在运行的Chrome/Chromium进程,否则主user-data-dir会被占用,还是会报错
  • 不要把进程数(threads参数)设得太大,每个Chrome实例占用的内存不低,太多进程会导致系统卡顿
  • 如果某些Profile子目录不存在,Chrome会自动创建,不用手动提前创建

备注:内容来源于stack exchange,提问作者ILP

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 17:23:08