首页 > 解决方案 > 无法使用 Selenium WebDriver Python 在 iframe 中找到元素

问题描述

我正在尝试在 www.investing.com 上自动加载图表。我的主要目的是单击“加载图表布局”按钮,该按钮可以在https://www.investing.com/charts/live-charts找到(图表 iframe 右上角的第三个按钮,看起来像云) . 作为 selenium 的新手,我了解了 iframe,经过一番检查,我发现该按钮位于 iframe 中,该 iframe 位于 iframe 中的 iframe 中。我终于正确地切换到包含按钮的 iframe,但由于某种原因,无论我使用类、id、xpath 还是其他任何东西,find_element_by_xxx 函数总是说找不到。我的代码如下

import time
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.common.exceptions import TimeoutException


def findFrames(driver):
    iframes = driver.find_elements_by_xpath('//iframe')
    i = 0
    index = 0
    for iframe in iframes:
        print(iframe.get_attribute('src'))

        string = iframe.get_attribute('src')
        if "tv" in string:
            index = i
            break
        i+=1
    print(index)
    return iframes, index

def main():
    chrome_options = Options()
    chrome_options.add_experimental_option("detach", True)
    #chrome_options.add_argument("/tmp/.com.google.Chrome.sBnz8G/Profile 1")
    driver = webdriver.Chrome(options=chrome_options)
    driver.get("http://www.investing.com")

    try:
        #time.sleep(10)
        driver.find_element_by_xpath("/html/body/div[5]/header/div[1]/div/div[4]/span[1]/div/a[1]").click()
        time.sleep(3)
    except:
        print("first block")

    try:
        WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.ID, 'loginPopup')))
        print("found")
    except:
        print("not found")

    try:
        elem = driver.find_element_by_id("loginFormUser_email")
        elem.click()
        elem.send_keys("my-email")
        elem = driver.find_element_by_id("loginForm_password")
        elem.click()
        elem.send_keys("my-password")
        elem.send_keys(Keys.ENTER)
        time.sleep(3)
    except: 
        print("second block")


    driver.find_element_by_xpath('//*[@id="navMenu"]/ul/li[5]/a').click()
    print("charts clicked")
    time.sleep(3)
    driver.find_element_by_xpath("/html/body/div[5]/section/div[4]/div[1]/a").click()
    print("live charts clicked")
    time.sleep(20)
    iframes, index = findFrames(driver)
    driver.switch_to.frame(iframes[index])
    print("switch 1")
    iframes, index = findFrames(driver)
    driver.switch_to.frame(iframes[index])
    print("switch 2")
    iframes, index = findFrames(driver)
    driver.switch_to.frame(iframes[index])
    print("switch 3")

    driver.find_element_by_xpath('/html/body/div[1]/div[2]/div/div/div[1]/div[3]/div/span[1]/svg').click() #THIS IS WHERE I GET THE ERROR
    print("successfully clicked load")
    time.sleep(1.5)


if __name__ == "__main__":
    main()

即使我切换到正确的框架,有人能找出为什么它说找不到吗?

标签: pythonseleniumselenium-webdriveriframewebdriver

解决方案


load chart layout存在于嵌套的内部iframes

处理动态元素 Induce WebDriverWait() 和frame_to_be_available_and_switch_to_it() 跟随css选择器

诱导WebDriverWait() 并等待element_to_be_clickable() 和后续css选择器

driver.find_element_by_xpath("/html/body/div[5]/section/div[4]/div[1]/a").click()
print("live charts clicked")
WebDriverWait(driver,10).until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR,"iframe[id^='tvc_frame']")))
WebDriverWait(driver,10).until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR,"iframe[src$='GB']")))
WebDriverWait(driver,10).until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR,"iframe[id^='tradingview']")))
WebDriverWait(driver,10).until(EC.element_to_be_clickable((By.CSS_SELECTOR,"div.save-load-buttons>span.load"))).click()
print("successfully clicked load")

您需要导入以下库

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

推荐阅读