在Firefox中通过Selenium访问ShadowRoot将返回JavascriptException:循环对象值

2024-06-01 00:46:52 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试使用Python和Selenium自动化www.freeinvaders.org版本的空间入侵者。实际的游戏通过一个HTML5画布元素工作,该元素被包装在一个阴影根中

使用this question的答案,我试图展开阴影根,这样我就可以单击画布并“玩”游戏了

我当前的代码:

  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。所有这些都在LinuxMint20.1上运行

编辑 我还尝试了另一种Javascript:

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

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

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

这表明它甚至找不到任何对象


Tags: namedivbrowserbycontainertag错误element
1条回答
网友
1楼 · 发布于 2024-06-01 00:46:52

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

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

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

按照返回shadowrootreturn 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()

相关问题 更多 >