【问题标题】:Can't switch to iframe and close the frame in Selenium using Python无法使用 Python 切换到 iframe 并关闭 Selenium 中的框架
【发布时间】:2020-09-04 13:45:22
【问题描述】:

在多次尝试从网站 (https://www.chemist.co.uk/) 获取详细信息均未成功后,我意识到几秒钟后会出现一个 iframe,并且该事件仅在网站打开时发生一次。但是,我发现很难处理 iframe,我尝试了各种方法,例如根据 index 和 id 查找 iframe,因为 iframe 没有名称。根据我的观察,这只会在我打开网站后发生。有人可以帮我弄清楚我做错了什么吗?

import os
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
currentdir = os.getcwd()


chrome_options = Options()
# chrome_options.add_argument('--headless')
chrome_options.add_argument("--disable-notifications")
chrome_options.add_argument('--no-sandbox')    
driver = webdriver.Chrome(executable_path=f"{currentdir}/chromedriver.exe", options=chrome_options)
# driver.maximize_window()
driver.implicitly_wait(20)
driver.get("https://www.chemist.co.uk/")
time.sleep(5)
# driver.switch_to.frame(1)
iframe = driver.find_element_by_id("AWIN_CDT")
driver.switch_to.frame(iframe)
driver.find_element_by_xpath("//a[@data-trigger='dismiss.close']").click()
driver.switch_to.default_content()

【问题讨论】:

    标签: python-3.x selenium iframe selenium-chromedriver


    【解决方案1】:

    不要使用 time.sleep,而是使用显式等待 iFrame 出现然后切换到它。您的页面中还有四个iframes。并且弹出窗口不在 ID 为 AWIN_CDT 的 iframe 内,而是在具有以下信息的第二帧内:

    <iframe scrolling="no" style="border: none; height: 1px; width: 100%; min-height: 100%; display: inline !important;"></iframe>
    

    因此,要关闭弹出窗口,您需要切换到此框架。

    driver.get('https://www.chemist.co.uk/')
    WebDriverWait(driver, 20).until(EC.frame_to_be_available_and_switch_to_it((By.XPATH,"//iframe[contains(@style,'border: none; height')]")))
    driver.find_element_by_xpath("//a[@data-trigger='dismiss.close']").click()
    driver.switch_to.default_content()
    

    您需要在下面导入

    from selenium import webdriver
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support import expected_conditions as EC
    

    【讨论】:

    • 你是如何找出 iframe 的?我试了很多次,但只能看到一个。既然您提到 iframe 不同,我意识到我正在查看错误的 iframe。无论如何,谢谢。
    • 这是一个有点野蛮的技术:P。如果您在检查模式下搜索元素,例如 //iframe[ ]//。它应该给我匹配。我确信这不是一种很容易发茬的方法,但它确实有效。
    • 好吧,考虑到单个网页中的两位数 iframe 并不常见,我想这是一个不错的方法。
    【解决方案2】:

    iframe 中存在的弹出元素,您需要先对其进行切换。但是该元素不存在您已识别的iframe

    诱导WebDriverWait()并等待frame_to_be_available_and_switch_to_it()及以下xpath

    诱导WebDriverWait()并等待element_to_be_clickable()及以下xpath

    from selenium import webdriver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    
    driver=webdriver.Chrome()
    driver.get("https://www.chemist.co.uk/")
    WebDriverWait(driver,20).until(EC.frame_to_be_available_and_switch_to_it((By.XPATH,"(//iframe[@scrolling='no'])[last()]")))
    WebDriverWait(driver,10).until(EC.element_to_be_clickable((By.XPATH,"//a[@data-trigger='dismiss.close']"))).click()
    driver.switch_to.default_content()
    

    单击弹出窗口后的浏览器快照。

    【讨论】:

    • 我也试过了,谢谢你的想法。我注意到刮板在 10 次中 2-3 次无法启动。在非无头模式下,我认为这与单击 iframe 的关闭按钮有关,因为在 iframe 发生后浏览器仍在等待。谢谢
    • 不知道为什么它最终会失败。我已经多次运行我的代码,但从未失败过。
    • 你认为这可能是因为互联网连接吗?因为当我尝试它时,基本上发生的情况是,如果网站像往常一样加载,它工作得很好,但如果网站无法立即加载 driver.implicitly_wait(15) 我相信会将这个过程延迟 15 秒。对不起,我忘了在这里提到它,但我在我的脚本中使用了它。
    • 你不需要隐式等待。只需复制并粘贴我的整个代码,让我知道状态如何。
    • 我只是从这部分开始我的脚本,我正在尝试抓取网站上所有产品的产品详细信息,所以我可能需要它。你曾经使用过隐式等待吗?还是 WebDriverWait 始终是您的首选方法?
    猜你喜欢
    • 2021-06-19
    • 1970-01-01
    • 1970-01-01
    • 2017-05-06
    • 1970-01-01
    • 2014-06-11
    • 2013-07-03
    • 2017-12-24
    • 1970-01-01
    相关资源
    最近更新 更多