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

基于VM与Streamlit的Web Scraping多Selenium会话运行问题求助

解决方案:Selenium多实例冲突与Playwright适配性分析

一、解决Selenium多实例并发问题的最简方案

因为你不熟悉多线程技术,任务队列+单工作线程是最易实现的方案,无需额外部署服务,直接在Streamlit中限制同时运行的抓取任务数:

核心思路

用全局队列存储用户提交的任务,启动一个后台线程依次处理队列中的任务,避免同时启动多个Selenium浏览器实例。

代码示例

import streamlit as st
from queue import Queue
from threading import Thread
from selenium import webdriver

# 全局任务队列,可根据VM资源调整最大任务数(比如设为2)
task_queue = Queue(maxsize=2)

def task_worker():
    while True:
        # 从队列获取任务
        task = task_queue.get()
        if task is None:
            break
        username, password = task
        
        # 执行Selenium抓取逻辑
        driver = webdriver.Chrome()
        try:
            driver.get("你的目标登录页面URL")
            # 填写登录表单(根据实际页面元素调整选择器)
            driver.find_element("id", "username").send_keys(username)
            driver.find_element("id", "password").send_keys(password)
            # 执行登录、抓取数据等操作
            # ... 替换为你的具体抓取代码
            st.success(f"用户「{username}」的抓取任务已完成")
        except Exception as e:
            st.error(f"任务失败:{str(e)}")
        finally:
            driver.quit()
        # 标记任务完成
        task_queue.task_done()

# 启动后台工作线程(仅启动一次)
if "worker_initialized" not in st.session_state:
    Thread(target=task_worker, daemon=True).start()
    st.session_state.worker_initialized = True

# Streamlit前端表单
st.title("网页抓取服务")
username = st.text_input("登录用户名")
password = st.text_input("登录密码", type="password")

if st.button("启动抓取"):
    if username and password:
        if task_queue.full():
            st.warning("当前任务队列已满,请稍后再试")
        else:
            task_queue.put((username, password))
            st.info("任务已加入队列,等待处理")
    else:
        st.error("请填写完整的用户名和密码")

二、Playwright是否更适配你的场景

是的,Playwright比Selenium更适合多用户Web服务场景,优势如下:

  • 无需额外驱动:自动下载对应浏览器,不用手动配置ChromeDriver等,减少部署麻烦
  • 资源占用更低:浏览器实例启动更快,内存占用比Selenium小,支持同时运行更多任务
  • 上下文隔离:每个任务可创建独立的BrowserContext,天然隔离不同用户的登录状态,避免冲突
  • API更简洁:语法更直观,学习成本更低,适合非专业开发者

Playwright最简实现示例

import streamlit as st
from queue import Queue
from threading import Thread
from playwright.sync_api import sync_playwright

task_queue = Queue(maxsize=2)

def task_worker():
    with sync_playwright() as p:
        # 复用浏览器实例,进一步降低资源消耗
        browser = p.chromium.launch(headless=True)
        while True:
            task = task_queue.get()
            if task is None:
                break
            username, password = task
            
            try:
                # 创建独立上下文,隔离用户会话
                context = browser.new_context()
                page = context.new_page()
                page.goto("你的目标登录页面URL")
                # 填写表单(选择器可根据实际页面调整)
                page.fill("#username", username)
                page.fill("#password", password)
                # 执行登录、抓取操作
                # ... 替换为你的具体抓取代码
                st.success(f"用户「{username}」的抓取任务已完成")
                context.close()
            except Exception as e:
                st.error(f"任务失败:{str(e)}")
            task_queue.task_done()
        browser.close()

# 启动工作线程
if "worker_initialized" not in st.session_state:
    Thread(target=task_worker, daemon=True).start()
    st.session_state.worker_initialized = True

# 前端表单(和Selenium版本一致)
st.title("网页抓取服务")
username = st.text_input("登录用户名")
password = st.text_input("登录密码", type="password")

if st.button("启动抓取"):
    if username and password:
        if task_queue.full():
            st.warning("当前任务队列已满,请稍后再试")
        else:
            task_queue.put((username, password))
            st.info("任务已加入队列,等待处理")
    else:
        st.error("请填写完整的用户名和密码")

三、方案选择建议

  • 如果不想更换现有工具:直接用Selenium+任务队列的方案,代码改动小,无需额外学习成本
  • 如果允许更换工具:优先选Playwright,它的设计更适合多用户并发场景,长期维护更简单

内容的提问来源于stack exchange,提问作者ozturkdk

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 03:43:16