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

如何用Selenium判断Discord是否需登录?解决同会话免登脚本异常

解决Discord网页端Selenium会话重复登录判断问题

问题描述

用Selenium访问discordapp.com/users/{user_id}({user_id}为个人Discord ID)时,首次会话流程正常:

  1. 加载URL后自动重定向至discord.com/channels/@me
  2. 弹出打开方式选择页,点击「Continue in browser」
  3. 显示登录表单,输入账号密码后点击「Log In」进入网页应用

但在同一个浏览器会话中多次运行函数时,无需再执行「Continue in browser」和登录步骤,导致Selenium的wait.until找不到对应元素,脚本直接停滞。

原代码如下:

import undetected_chromedriver as uc
from fake_useragent import UserAgent
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as ec
from selenium.webdriver.support.ui import WebDriverWait

chrome_options = uc.options.ChromeOptions()
prefs = {"credentials_enable_service": False, "profile.password_manager_enabled": False}
chrome_options.add_experimental_option("prefs", prefs)
chrome_options.add_argument('--no-sandbox')
chrome_options.add_argument('--disable-dev-shm-usage')
#chrome_options.add_argument('--headless=new')
chrome_options.add_argument(f'user-agent={UserAgent().random}')
driver = uc.Chrome(options=chrome_options)
wait = WebDriverWait(driver, 10)

def x_discord(user_id):
    
    driver.get(f"https://discordapp.com/users/{user_id}")
    try:
        wait.until(ec.visibility_of_element_located((By.XPATH, "//div[contains(text(), 'Continue in browser')]"))).click()
        wait.until(ec.visibility_of_element_located((By.NAME, "email"))).send_keys('login')
        wait.until(ec.visibility_of_element_located((By.NAME, "password"))).send_keys('password')
        wait.until(ec.visibility_of_element_located((By.XPATH, "//div[contains(text(), 'Log In')]"))).click()
    finally:
        wait.until(ec.url_contains("@me"))
   
    # rest of function...     
   
    # driver.close()
    return result

已尝试的方法:

  • 使用wait.until(ec.url_to_be(url)),但重定向后URL始终固定为discord.com/channels/@me,无法区分登录状态
  • 考虑添加计数器标记首次运行状态,但灵活性差,无法处理会话意外过期的情况
  • 尝试用driver.close()和driver.quit()重置会话,但无法重新启动新会话
  • 读取localStorage的email_cache判断登录状态,但实际运行中稳定性不足

可行优化方案

方案1:针对每个交互元素做存在性检查(try-except捕获超时)

核心逻辑:不再默认每次都需要执行登录流程,而是对每个需要点击/输入的元素单独做存在性验证,元素不存在则直接跳过,避免等待超时卡住脚本。

修改后的代码:

def x_discord(user_id):
    driver.get(f"https://discordapp.com/users/{user_id}")
    
    # 检查并点击「Continue in browser」按钮
    try:
        continue_btn = wait.until(ec.visibility_of_element_located((By.XPATH, "//div[contains(text(), 'Continue in browser')]")))
        continue_btn.click()
    except:
        # 元素不存在,跳过该步骤
        pass
    
    # 检查并填写登录表单
    try:
        email_input = wait.until(ec.visibility_of_element_located((By.NAME, "email")))
        email_input.send_keys('your_login_email')
        password_input = wait.until(ec.visibility_of_element_located((By.NAME, "password")))
        password_input.send_keys('your_login_password')
        login_btn = wait.until(ec.visibility_of_element_located((By.XPATH, "//div[contains(text(), 'Log In')]")))
        login_btn.click()
    except:
        # 已处于登录状态,跳过登录流程
        pass
    
    # 确保页面加载完成(等待目标URL或登录后专属元素)
    wait.until(ec.url_contains("@me"))
    
    # rest of function...     
    return result

方案2:通过登录后专属元素判断状态

Discord登录成功后,页面会显示用户头像、侧边栏导航等专属元素,通过检查这些元素的存在性判断是否已登录,比依赖localStorage更可靠。

示例代码:

def is_logged_in():
    try:
        # 检查登录后的用户头像元素(可根据实际页面结构调整XPATH/CSS选择器)
        wait.until(ec.visibility_of_element_located((By.XPATH, "//div[@class='avatarWrapper-1B9FTW']")))
        return True
    except:
        return False

def x_discord(user_id):
    driver.get(f"https://discordapp.com/users/{user_id}")
    
    if not is_logged_in():
        # 处理「Continue in browser」弹窗
        try:
            continue_btn = wait.until(ec.visibility_of_element_located((By.XPATH, "//div[contains(text(), 'Continue in browser')]")))
            continue_btn.click()
        except:
            pass
        
        # 执行登录操作
        wait.until(ec.visibility_of_element_located((By.NAME, "email"))).send_keys('your_login_email')
        wait.until(ec.visibility_of_element_located((By.NAME, "password"))).send_keys('your_login_password')
        wait.until(ec.visibility_of_element_located((By.XPATH, "//div[contains(text(), 'Log In')]"))).click()
        # 等待登录完成,直到检测到登录后元素
        wait.until(is_logged_in())
    
    # rest of function...     
    return result

方案3:持久化浏览器会话(可选)

如果需要长期保持登录状态,可以在初始化Chrome时指定用户数据目录,让浏览器保留登录凭证,无需每次重复登录:

# Windows示例路径
chrome_options.add_argument(r"--user-data-dir=C:\Users\YourName\AppData\Local\Google\Chrome\User Data")
# Linux/Mac示例路径
# chrome_options.add_argument(r"--user-data-dir=/home/yourname/.config/google-chrome/Default")

关键注意事项

  • 避免硬编码元素定位符,Discord页面结构可能更新,建议定期检查XPATH/CSS选择器,优先使用稳定的属性(如ID、唯一类名)
  • 根据网络情况调整WebDriverWait的超时时间,避免因加载慢导致误判
  • 使用undetected_chromedriver时,确保其版本与本地Chrome版本匹配,避免兼容性问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 20:13:25