![](/img/trans.png)
[英]Python Selenium - How to fix WebDriverException: Message: target frame detached
[英]How to address “WebDriverException: Message: TypeError: can't access dead object” and wait for a frame to be available using Selenium and Python
我有一個相當復雜的網頁設置需要測試,其中包含嵌套框架。
在實際問題中,selenium 代碼正在加載包含框架的新網頁內容,我想切換到該框架。 為了避免任何顯式等待,我嘗試了以下代碼片段:
self.driver.switch_to_default_content()
WebDriverWait(self.driver, 300).\
until(EC.frame_to_be_available_and_switch_to_it((By.ID, 'frame1')))
WebDriverWait(self.driver, 300).\
until(EC.frame_to_be_available_and_switch_to_it((By.ID, 'frame2')))
但是,此代碼段總是失敗並導致以下錯誤:
...
File "/home/adietz/Projects/Venv/nosetests/local/lib/python2.7/site-packages/selenium/webdriver/support/wait.py", line 71, in until
value = method(self._driver)
File "/home/adietz/Projects/Venv/nosetests/local/lib/python2.7/site-packages/selenium/webdriver/support/expected_conditions.py", line 247, in __call__
self.frame_locator))
File "/home/adietz/Projects/Venv/nosetests/local/lib/python2.7/site-packages/selenium/webdriver/support/expected_conditions.py", line 402, in _find_element
raise e
WebDriverException: Message: TypeError: can't access dead object
但是,如果我另外使用睡眠:
time.sleep(30)
self.driver.switch_to_default_content()
WebDriverWait(self.driver, 300).\
until(EC.frame_to_be_available_and_switch_to_it((By.ID, 'frame1')))
WebDriverWait(self.driver, 300).\
until(EC.frame_to_be_available_and_switch_to_it((By.ID, 'frame2')))
selenium 能夠在框架內找到框架並切換到它。 看起來在錯誤情況下 selenium 切換到 'frame1' 而 'frame2' 尚未加載,但 'frame2' 已加載到 'frame1' 的其他實例中,或者 selenium 無法識別(可能是錯誤?)。 所以現在硒在一些“frame1”中,並且由於某些原因沒有意識到“frame2”已被加載。
我可以解決這個問題(不使用長時間睡眠)的唯一方法是使用這段丑陋的代碼:
mustend = time.time() + 300
while time.time() < mustend:
try:
self.driver.switch_to_default_content()
self.driver.switch_to.frame(self.driver.find_element_by_id("frame1"))
self.driver.switch_to.frame(self.driver.find_element_by_id("frame2"))
break
except WebDriverException as e:
self.log("Sleeping 1 sec")
time.sleep(1)
if time.time() > mustend:
raise TimeoutException
因此,每當我收到WebDriverException
(死對象)時,我都會轉到頂層框架並嘗試切換到內部框架 - 逐幀。
還有其他方法可以嘗試嗎?
附加信息
更好的方法是讓你自己的expected_condition。 例如:
class nested_frames_to_be_available_and_switch:
def __init__(self, *args):
"""
:param args: locators tuple of nested frames (BY.ID, "ID1"), (BY.ID, "ID2"), ...
"""
self.locators = args
def __call__(self, driver):
try:
for locator in self.locators:
driver.switch_to.frame(driver.find_element(*locator))
except WebDriverException:
driver.switch_to_default_content()
return False
return True
WebDriverWait(driver, 300).until(nested_frames_to_be_available_and_switch((By.ID, 'frame1'), (By.ID, 'frame1')))
但也許沒有必要......說我需要看看你的 html DOM。
這個錯誤信息...
WebDriverException: Message: TypeError: can't access dead object
...暗示在<iframes>
之間切換時出現錯誤。
在以下方面的更多信息:
<iframe>
標簽中存在JavaScript和AJAX 調用會幫助我們以更好的方式分析問題。 然而,在這一點上值得一提的是,最初Selenium總是將焦點放在default_content 上。 以下是使用嵌套<frames>
和<framesets>
的幾種方法:
如果frame1和frame2處於同一級別,即在頂級瀏覽上下文下,您需要:
self.driver.switch_to.frame(self.driver.find_element_by_id("frame1")) self.driver.switch_to_default_content() self.driver.switch_to.frame(self.driver.find_element_by_id("frame2"))
如果frame2嵌套在frame1 中,要從frame1切換到frame2,您需要:
self.driver.switch_to_default_content() self.driver.switch_to.frame(self.driver.find_element_by_id("frame1")) //code self.driver.switch_to.frame(self.driver.find_element_by_id("frame2"))
如果幀2和幀3的幀1中,然后,切換從幀2到你需要幀3:
self.driver.switch_to.frame(self.driver.find_element_by_id("frame2")) self.driver.switch_to.frame(self.driver.find_element_by_id("frame1")) self.driver.switch_to.frame(self.driver.find_element_by_id("frame3"))
如果幀2和幀3是frameset23是幀1中那么,交換機從幀2到幀3中您需要:
self.driver.switch_to.frame(self.driver.find_element_by_id("frame2")) #ignore presence of frameset23 self.driver.switch_to.frame(self.driver.find_element_by_id("frame1")) #ignore presence of frameset23 self.driver.switch_to.frame(self.driver.find_element_by_id("frame3"))
在處理iframe和框架集時,您需要將WebDriverWait與expected_conditions 結合起來:
frame_to_be_available_and_switch_to_it()
作為從頂級瀏覽上下文切換到<iframe>
的示例,有效的代碼行將是:
使用幀ID:
WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it((By.ID,"frameID")))
使用框架名稱:
WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it((By.NAME,"frameNAME")))
使用框架CLASS_NAME:
WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it((By.frame_CLASS_NAME,"u_0_f")))
使用框架CSS_SELECTOR:
WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR,"frame_CSS_SELECTOR")))
使用框架XPATH:
WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it((By.XPATH,"frame_XPATH")))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.