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

登录后使用Python Selenium ActionChains触发JavascriptException: Cyclic object value错误

登录后使用Python Selenium ActionChains触发JavascriptException: Cyclic object value错误

你遇到的这个问题确实挺让人头疼的——明明上周还正常,现在只要在自定义的登录函数之后调用ActionChains执行Ctrl+Click打开新标签,就会抛出JavascriptException: Message: Cyclic object value,但登录前完全正常。

先还原下你的场景:

  • 环境:Python 3 + Jupyter Notebook + Selenium Firefox驱动
  • 登录前测试ActionChains完全成功:
import time
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.keys import Keys

driver = webdriver.Firefox()

driver.get('http://google.com')
element = driver.find_element(By.LINK_TEXT, 'Terms')

for x in range(1,5):
    ActionChains(driver) \
        .key_down(Keys.CONTROL) \
        .click(element) \
        .key_up(Keys.CONTROL) \
        .perform()
print("Upstream of login ActionChains successful")
  • 调用login函数后,同样的操作就报错:
login(driver)

element2 = driver.find_element(By.LINK_TEXT, 'About')

ActionChains(driver) \
    .key_down(Keys.CONTROL) \
    .click(element2) \
    .key_up(Keys.CONTROL) \
    .perform()
print("Downstream of login ActionChains successful")
  • 报错栈指向Selenium的W3C Actions序列化环节,是Firefox Marionette驱动在处理JS对象时碰到了循环引用。

可能的原因和解决办法

原因分析

这个错误本质是Selenium的W3C Actions API在序列化动作指令时,遇到了页面中存在循环引用的JS对象(比如页面全局变量、第三方脚本创建的循环引用结构)。登录后的页面跳转改变了浏览器的JS上下文,刚好触发了这个问题。

具体解决方案

1. 用原生JS替代ActionChains实现开新标签

最稳妥的办法是绕开ActionChains,直接调用浏览器的JS API打开新标签,完全避免动作序列化的问题:

# 替换原来的ActionChains代码
element2 = driver.find_element(By.LINK_TEXT, 'About')
driver.execute_script("window.open(arguments[0].href, '_blank');", element2)

这种方式兼容性更好,也不会受页面JS上下文的影响。

2. 重置ActionChains的动作上下文

在登录后显式重置ActionChains的状态,清空之前的动作缓存:

login(driver)

# 重置ActionChains的动作队列
actions = ActionChains(driver)
actions.reset_actions()

element2 = driver.find_element(By.LINK_TEXT, 'About')
actions.key_down(Keys.CONTROL)\
       .click(element2)\
       .key_up(Keys.CONTROL)\
       .perform()

同时可以在登录后加上页面焦点重置,确保浏览器上下文正常:

driver.execute_script("window.focus();")
3. 优化登录函数的页面跳转方式

你的login函数最后用link.send_keys(Keys.RETURN)跳转页面,换成link.click()可能会避免一些上下文异常:

def login(driver, username, password):
    driver.implicitly_wait(5)
    driver.get("http://mywebsite.com")
    elem = driver.find_element(By.ID, "Username")
    elem.clear()
    elem.send_keys(username)
    elem = driver.find_element(By.ID, "Password")
    elem.clear()
    elem.send_keys(password)
    
    elem.send_keys(Keys.RETURN)

    # 替换成click()跳转
    link = driver.find_element(By.ID, "NextSection")
    link.click()
    
    return 
4. 确保页面完全加载后再执行操作

登录后等待页面完全加载完成,避免在页面JS未初始化完成时执行ActionChains:

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

login(driver)
# 显式等待目标元素加载完成
WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.LINK_TEXT, 'About')))

# 再执行操作
element2 = driver.find_element(By.LINK_TEXT, 'About')
ActionChains(driver)\
    .key_down(Keys.CONTROL)\
    .click(element2)\
    .key_up(Keys.CONTROL)\
    .perform()

尝试上面的方法,应该能解决你遇到的循环对象值报错问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 09:23:04