【问题标题】:Selenium WebDriverWait can't wait for execute_script twice?Selenium WebDriverWait 不能等待 execute_script 两次?
【发布时间】:2022-01-06 02:38:16
【问题描述】:

我尝试通过execute_script()获取页面中的shadowRoot元素,不想使用time.sleep(),所以选择了WebDriverWait。当我第一次调用 WebDriverWait.until() 时,它似乎真的在等待;当我第二次调用 WebDriverWait.until() 时,它似乎没有等待,并且 Chrome 在调用了 maximum_window() 后退出了。最后输出如下错误。

from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as wait
from selenium.webdriver.common.keys import Keys


with webdriver.Chrome() as browser:
    wait = WebDriverWait(browser, 30, 1)
    
    browser.get("https://www.virustotal.com/gui/home/search")

    element = wait.until(
        lambda browser: browser.execute_script("""return document.querySelector('home-view').shadowRoot.querySelector('vt-ui-search-bar').shadowRoot.querySelector('vt-ui-text-input')""")
    )

    if element:
        element.send_keys('5f580868011b6c0deb8bde8355630019')
        element.send_keys(Keys.RETURN)
    
        browser.maximize_window()

        #Must be using time.sleep() ???
        
        result = wait.until(
            lambda browser: browser.execute_script("""return document.querySelector('file-view').shadowRoot.querySelector('vt-ui-file-card').shadowRoot.querySelector('vt-ui-generic-card').children[1].textContent.trim()""")
        )

        if result:
            print(result)
DevTools listening on ws://127.0.0.1:12247/devtools/browser/11eba3c5-3044-4835-94a9-8db6b56687f4
Traceback (most recent call last):
  File "d:\source\VsCode\py\jupyter\test15.py", line 22, in <module>
    result = wait.until(
  File "D:\Program Files\Python39\lib\site-packages\selenium\webdriver\support\wait.py", line 78, in until
    value = method(self._driver)
  File "d:\source\VsCode\py\jupyter\test15.py", line 23, in <lambda>
    lambda browser: browser.execute_script("""return document.querySelector('file-view').shadowRoot.querySelector('vt-ui-file-card').shadowRoot.querySelector('vt-ui-generic-card').children[1].textContent.trim()""")
  File "D:\Program Files\Python39\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 878, in execute_script
    return self.execute(command, {
  File "D:\Program Files\Python39\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 424, in execute
    self.error_handler.check_response(response)
  File "D:\Program Files\Python39\lib\site-packages\selenium\webdriver\remote\errorhandler.py", line 247, in check_response
    raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.JavascriptException: Message: javascript error: Cannot read properties of null (reading 'shadowRoot')
  (Session info: chrome=97.0.4692.71)
Stacktrace:
Backtrace:
        Ordinal0 [0x008A6903+2517251]
        Ordinal0 [0x0083F8E1+2095329]
        Ordinal0 [0x00742848+1058888]
        Ordinal0 [0x00744F44+1068868]
        Ordinal0 [0x00744E0E+1068558]
        Ordinal0 [0x007456BA+1070778]
        Ordinal0 [0x007964F9+1402105]
        Ordinal0 [0x007864D3+1336531]
        Ordinal0 [0x00795BBF+1399743]
        Ordinal0 [0x0078639B+1336219]
        Ordinal0 [0x007627A7+1189799]
        Ordinal0 [0x00763609+1193481]
        GetHandleVerifier [0x00A35904+1577972]
        GetHandleVerifier [0x00AE0B97+2279047]
        GetHandleVerifier [0x00936D09+534521]
        GetHandleVerifier [0x00935DB9+530601]
        Ordinal0 [0x00844FF9+2117625]
        Ordinal0 [0x008498A8+2136232]
        Ordinal0 [0x008499E2+2136546]
        Ordinal0 [0x00853541+2176321]
        BaseThreadInitThunk [0x7683FA29+25]
        RtlGetAppContainerNamedObjectPath [0x76FB7A9E+286]
        RtlGetAppContainerNamedObjectPath [0x76FB7A6E+238]

【问题讨论】:

    标签: python selenium selenium-webdriver


    【解决方案1】:

    默认情况下,until 仅处理 TimeoutException,但您在尝试从 shadowRoot 获取属性之一时得到 JavascriptException,该属性尚不存在,因此是 nullUntil 可以处理 null/None 结果,但只能在返回值上,而不是在执行条件方法时。

    一种解决方案(并且更简单)是在创建 WebDriverWait 实例时将 JavascriptException 添加到 ignored_exceptions 列表中

    wait = WebDriverWait(browser, 30, 1, ignored_exceptions=JavascriptException)
    

    另一种解决方案是将脚本拆分为多个部分,并每次检查shadowRoot 的可用性

    result = wait.until(
        lambda browser: browser.execute_script(
            """
            value = document.querySelector('file-view').shadowRoot.querySelector('vt-ui-file-card');
            if (value) {
                value = value.shadowRoot.querySelector('vt-ui-generic-card');
                if (value) {
                    value = value.children[1].textContent.trim();
                }
            }
            return value;""")
    )
    

    【讨论】:

    • 我运行了这段代码,它似乎完成了这项工作。 OP 必须更改 querySelector 以获得所需的输出,现在输出为 db4ac82d2c8db0dbc73e772b0b02c9e3917bbf13363bc37a0001dd2851304a4a pythompy2 1.17 MB Size 2019-12-09 09:51:35 UTC
    • 由于网络原因,请求和响应都比较慢。在第二次调用 execute_script() 之前我应该​​等待一段时间吗?如果我使用 time.sleep() 来等待显示,wait.until() 还有意义吗?
    • @fs 你可以随时增加WebDriverWait中定义的时间
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-21
    • 1970-01-01
    • 2019-12-02
    • 2021-04-01
    • 2022-01-23
    • 1970-01-01
    • 2015-10-21
    相关资源
    最近更新 更多