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

Django实现WhatsApp定时消息会话:二维码会话保持问题求助

WhatsApp Web会话管理问题解决方案

问题描述

我正在开发一个系统,用户除完成相关流程外,可注册客户的WhatsApp账号,用来发送自动账单、祝福等消息。用户扫码后,系统会用该WhatsApp账号定时发消息,搭建用户和客户的对话通道。目前已实现读取WhatsApp Web二维码并在模板显示,但遇到两个问题:

  • 返回模板后WebDriver提前终止,导致会话无法验证
  • WebDriver持续处于开启状态,无法合理释放资源

需要解决这个并发任务的资源管理问题。

当前代码

# views.py
from django.shortcuts import render
from django.http import HttpResponse
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import base64
import time
from django.shortcuts import render

def read_qr_code(request):
    driver = webdriver.Firefox()
    # driver.implicitly_wait(30) # mantém o webdriver ativo por 2 minutos
    driver.get('https://web.whatsapp.com/')
    wait = WebDriverWait(driver, 10)
    qr_element = wait.until(EC.presence_of_element_located((By.XPATH, '//*[@id="app"]/div/div/div[3]/div[1]/div/div/div[2]/div/canvas')))


    qr_image_binary = qr_element.screenshot_as_png
    qr_image_base64 = base64.b64encode(qr_image_binary).decode('utf-8')

    context = {
        'image_data': qr_image_base64
    }

    # send_qr(request, context)
    
    # time.sleep(20)  # aguarda por 2 minutos
    # driver.quit()  # fecha o webdriver

    return render(request, 'read_qr_code.html', context)

解决方案

1. 剥离WebDriver生命周期到后台任务

视图函数是同步请求响应模型,一旦返回模板,当前进程资源会被回收,导致WebDriver被终止。必须把WebDriver的管理逻辑放到后台异步任务中:

  • 使用Celery这类异步任务框架,将WebDriver初始化、二维码获取、会话等待逻辑封装成后台任务
  • 视图只负责触发任务,前端通过轮询或WebSocket获取二维码和会话验证状态
  • 示例简化代码:
# tasks.py
from celery import Celery
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import base64

app = Celery('whatsapp_tasks', broker='redis://localhost:6379/0')

@app.task(bind=True)
def start_whatsapp_session(self):
    driver = webdriver.Firefox()
    driver.get('https://web.whatsapp.com/')
    try:
        # 获取二维码并更新任务状态
        qr_element = WebDriverWait(driver, 10).until(
            EC.presence_of_element_located((By.XPATH, '//*[@id="app"]/div/div/div[3]/div[1]/div/div/div[2]/div/canvas'))
        )
        qr_base64 = base64.b64encode(qr_element.screenshot_as_png).decode('utf-8')
        self.update_state(state='QR_READY', meta={'qr_code': qr_base64})
        
        # 等待用户扫码验证,超时设为5分钟
        WebDriverWait(driver, 300).until(
            EC.presence_of_element_located((By.XPATH, '//*[@id="app"]/div/div/div[4]/div/header/div[2]/div[2]/span'))
        )
        
        # 保存会话信息,后续可复用
        session_data = {
            'cookies': driver.get_cookies(),
            'user_name': driver.find_element(By.XPATH, '//*[@id="app"]/div/div/div[4]/div/header/div[2]/div[2]/span').text
        }
        return {'status': 'SUCCESS', 'session': session_data}
    finally:
        # 验证完成后可选择关闭Driver,或保留用于后续消息发送
        # driver.quit()
        pass

# views.py
from django.shortcuts import render
from django.http import JsonResponse
from .tasks import start_whatsapp_session

def qr_page(request):
    return render(request, 'read_qr_code.html')

def start_session(request):
    if request.method == 'POST':
        task = start_whatsapp_session.delay()
        return JsonResponse({'task_id': task.id})

def check_session_status(request, task_id):
    task = start_whatsapp_session.AsyncResult(task_id)
    if task.state == 'QR_READY':
        return JsonResponse({'state': task.state, 'qr_code': task.info['qr_code']})
    elif task.state == 'SUCCESS':
        return JsonResponse({'state': task.state, 'session': task.info['session']})
    return JsonResponse({'state': task.state})

2. 会话持久化与复用

验证成功后,保存WebDriver的Cookie到数据库,下次需要发送消息时,直接加载Cookie恢复会话,无需重新扫码:

# 恢复会话示例
driver = webdriver.Firefox()
driver.get('https://web.whatsapp.com/')
# 从数据库读取之前保存的cookies
for cookie in saved_cookies:
    driver.add_cookie(cookie)
driver.refresh()
# 此时会话已恢复,可直接发送消息

3. 闲置资源清理

  • 给后台任务设置超时时间,超过5分钟未验证的会话自动触发driver.quit()
  • 定时扫描后台任务列表,关闭长时间闲置的WebDriver实例
  • 可以用Celery的task_time_limit参数设置任务超时:
@app.task(bind=True, task_time_limit=300)
def start_whatsapp_session(self):
    # 任务逻辑

4. 替代方案:使用官方API

如果业务场景允许,优先选择WhatsApp Business API,无需依赖Selenium模拟浏览器,稳定性和可靠性更高,也能彻底避免WebDriver的资源管理问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 09:30:57