【问题标题】:Accessing ShadowRoot via Selenium in Firefox returns JavascriptException: Cyclic object value在 Firefox 中通过 Selenium 访问 ShadowRoot 返回 JavascriptException: Cyclic object value
【发布时间】:2021-07-11 23:12:51
【问题描述】:

我正在尝试使用 Python 和 Selenium 自动化 Space Invaders 的 www.freeinvaders.org 版本。实际游戏通过 HTML5 画布元素运行,该元素被包裹在 shadow-root 中。

使用this question 的答案,我正在尝试扩展 shadow-root,以便我可以单击画布并“玩”游戏。

我当前的代码:

  def expand_shadow_element(element):
     shadowRoot = browser.execute_script('return arguments[0].shadowRoot', element)
     return shadowRoot
  

  browser = webdriver.Firefox()
  browser.get("http://www.freeinvaders.org/")

  #wait for element to load

  el = WebDriverWait(browser, timeout=20).until(lambda d:d.find_element_by_tag_name("ruffle-player"))
  time.sleep(5)

  #expand the shadowroot and click the canvas
  host = browser.find_element_by_tag_name("ruffle-player")
  shadowRoot = expand_shadow_element(host)
  canvas = shadowRoot.find_element_by_tag_name("canvas")
  canvas.click()

页面的HTML结构是这样的: (为便于阅读而删节)

<!DOCTYPE html> 
<html lang="en-US">
<head>

<title>Free Invaders</title>

</head>
<body>
<div id='full-page-container'>  
<main>
  <div id="game-container">
       
    <ruffle-player>
  #shadow-root (open)
  <div id="container" style="visibility: visible;">
      
    <canvas width="1600" height="760" style="touch-action: none; cursor: auto;"></canvas>
    </div><!--container-->
  </ruffle-player>
  </div><!--game-container-->

</div><!--fullpagecontainer-->
</body>

运行上述 Pyhton 脚本时,在这一行失败:

shadowRoot = browser.execute_script('return arguments[0].shadowRoot', element)

出现 Javascript 错误:

selenium.common.exceptions.JavascriptException: Message: Cyclic object value

我知道错误应该意味着返回的 JSON 字符串中有一个自引用项,但这里不应该是这种情况。

谁能帮助我解释为什么会出现这个错误以及采取什么行动可以缓解这个问题?

我正在使用 Python 3.8.5、Selenium 3.141.0 和 Firefox 86.0。所有这些都在 Linux Mint 20.1 上运行。

编辑 我还尝试了替代 Javascript:

shadowRoot = browser.execute_script('document.querySelector("ruffle-player").shadowRoot')

但这只会返回另一个错误:

AttributeError: 'NoneType' object has no attribute 'find_element_by_tag_name'

这表明它甚至没有找到任何对象。

【问题讨论】:

  • 好吧,显然这在 Chrome 中确实有效,我在盯着它看了好几天后不情愿地安装了它。这有点虎头蛇尾,因为它不是我的代码有什么问题,而是(显然)是 Firefox 或 Geckodriver 中的一个错误。尽管如此,我将至少在赏金到期之前将这个问题保持开放,看看是否有人有专门针对 Firefox 的解决方案。
  • 我无法访问您在我的笔记本电脑上共享的网页,因为我这边还有一些防火墙,但是您可以参考stackoverflow.com/questions/56380091/… 以了解 shadow-root 及其实施处理它们的选项。
  • 谢谢,但这个答案虽然内容丰富,但最终指的是我已经在我的代码中实现的解决方案。正如我在上面的评论中所指出的,该解决方案适用于带有 Chromedriver 的 Chrome,但不适用于带有 Geckodriver 的 Firefox。

标签: javascript python selenium


【解决方案1】:

这似乎是在bugzilla 提交的一个已知问题。

geckodriver 开发人员还说 WebDriver 规范需要更新。见:w3c/webdriver#350

但是,CAVAh 找到并发布了解决此问题的解决方法here

按照建议返回 shadowroot return arguments[0].shadowRoot.children 的孩子,它会找到 4 个元素:

[<selenium.webdriver.firefox.webelement.FirefoxWebElement (session="1dd0fedf-1a8c-42f2-a4de-0ed7df478212", element="252a6352-4fe0-409d-a626-18456a973da5")>, 
<selenium.webdriver.firefox.webelement.FirefoxWebElement (session="1dd0fedf-1a8c-42f2-a4de-0ed7df478212", element="47d76aed-5f44-4933-9718-53267a6417bf")>, 
<selenium.webdriver.firefox.webelement.FirefoxWebElement (session="1dd0fedf-1a8c-42f2-a4de-0ed7df478212", element="d3fcad48-7cbb-4de3-a247-49d7d227e982")>, 
<selenium.webdriver.firefox.webelement.FirefoxWebElement (session="1dd0fedf-1a8c-42f2-a4de-0ed7df478212", element="abb5012e-79bf-494b-b5f2-ff28dfecab0f")>]

在检查了这些之后,看起来第三个元素包含画布并且可以点击。

以下代码似乎对我有用:

def expand_shadow_element(element):
    # return a list of elements
    shadowRoot = browser.execute_script('return arguments[0].shadowRoot.children', element)
    return shadowRoot


browser = webdriver.Firefox()
browser.get("http://www.freeinvaders.org/")

#wait for element to load

el = WebDriverWait(browser, timeout=20).until(lambda d:d.find_element_by_tag_name("ruffle-player"))
time.sleep(5)

#expand the shadowroot and click the canvas
host = browser.find_element_by_tag_name("ruffle-player")
shadowRoot = expand_shadow_element(host)

canvas = shadowRoot[2].find_element_by_tag_name("canvas")
canvas.click()

【讨论】:

  • 优秀。谢谢!
猜你喜欢
  • 2017-08-12
  • 2020-05-30
  • 2017-10-29
  • 2014-09-08
  • 2019-10-18
  • 2022-06-14
  • 2011-10-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多