为什么 CSS 选择器在等待元素可点击后无法点击元素?
Why is CSS Selector not able to click on element after waiting for element to be clickable?
查看下面的代码。我认为除了最后一行,你几乎可以忽略所有内容。
from selenium import webdriver
import os
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import xlsxwriter
from datetime import datetime
import time
chrome_driver = os.path.abspath('C:/Users/ross/Desktop/chromedriver.exe')
browser = webdriver.Chrome(chrome_driver)
browser.get('https://finra-markets.morningstar.com/BondCenter/Default.jsp')
WebDriverWait(browser, 60).until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#TabContainer > div > div.rtq-tab-wrap > div.rtq-tab-menus-wrap > ul > li:nth-child(3) > a > span'))).click()
WebDriverWait(browser, 60).until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#firscreener-cusip'))).send_keys("STWD")
WebDriverWait(browser, 60).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#ms-finra-advanced-search-form > div.ms-finra-advanced-search-btn > input:nth-child(2)"))).click()
WebDriverWait(browser, 60).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#ms-agreement > input"))).click()
WebDriverWait(browser, 60).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#ms-finra-search-results > div > div.qs-resultData > div.qs-resultData-body > div.rtq-grid.rtq-grid-auto-h > div.rtq-grid-hd > div > div:nth-child(7) > div"))).click()
time.sleep(2)
WebDriverWait(browser, 60).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#ms-finra-search-results > div > div.qs-resultData > div.qs-resultData-body > div.rtq-grid.rtq-grid-auto-h > div.rtq-grid-hd > div > div:nth-child(7) > div"))).click()
time.sleep(2)
whole_chart = WebDriverWait(browser, 60).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#ms-finra-search-results > div > div.qs-resultData > div.qs-resultData-body > div.rtq-grid.rtq-grid-auto-h > div.rtq-scrollpanel > div.rtq-grid-scroll"))).text
parent = browser.find_element_by_xpath('//*[@id="ms-finra-search-results"]/div/div[3]/div[1]/div[1]/div[2]/div[2]/div')
count_divs = len(parent.find_elements_by_xpath("./div"))
for row_num in range(1):
symbol = WebDriverWait(browser, 60).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#ms-finra-search-results > div > div.qs-resultData > div.qs-resultData-body > div.rtq-grid.rtq-grid-auto-h > div.rtq-scrollpanel > div.rtq-grid-scroll > div > div:nth-child(" + str(row_num + 1) + ") > div:nth-child(3)"))).text
maturity = WebDriverWait(browser, 60).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#ms-finra-search-results > div > div.qs-resultData > div.qs-resultData-body > div.rtq-grid.rtq-grid-auto-h > div.rtq-scrollpanel > div.rtq-grid-scroll > div > div:nth-child(" + str(row_num + 1) + ") > div:nth-child(7)"))).text
moody_rating = WebDriverWait(browser, 60).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#ms-finra-search-results > div > div.qs-resultData > div.qs-resultData-body > div.rtq-grid.rtq-grid-auto-h > div.rtq-scrollpanel > div.rtq-grid-scroll > div > div:nth-child(" + str(row_num + 1) + ") > div:nth-child(8)"))).text
sandp_rating = WebDriverWait(browser, 60).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#ms-finra-search-results > div > div.qs-resultData > div.qs-resultData-body > div.rtq-grid.rtq-grid-auto-h > div.rtq-scrollpanel > div.rtq-grid-scroll > div > div:nth-child(" + str(row_num + 1) + ") > div:nth-child(9)"))).text
bond_yield = WebDriverWait(browser, 60).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#ms-finra-search-results > div > div.qs-resultData > div.qs-resultData-body > div.rtq-grid.rtq-grid-auto-h > div.rtq-scrollpanel > div.rtq-grid-scroll > div > div:nth-child(" + str(row_num + 1) + ") > div:nth-child(11)"))).text
if symbol.strip() and maturity.strip() and moody_rating.strip() and sandp_rating.strip() and bond_yield.strip() and moody_rating != "WR" and sandp_rating != "NR":
WebDriverWait(browser, 60).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#ms-finra-search-results > div > div.qs-resultData > div.qs-resultData-body > div.rtq-grid.rtq-grid-auto-h > div.rtq-scrollpanel > div.rtq-grid-scroll > div > div:nth-child(" + str(row_num + 1) + ") > div:nth-child(2) > div > a"))).click()
WebDriverWait(browser, 60).until(EC.element_to_be_clickable((By.CSS_SELECTOR,"#tradeHistory_link"))).click()
基本上,我进入了这个页面:https://finra-markets.morningstar.com/BondCenter/BondDetail.jsp?ticker=C724231&symbol=STWD4571190,我希望 Selenium 单击它上面的 'Trade History' link,所以我引用了选择器 '#tradeHistory_link '.出于某种原因,它没有点击,当我尝试只获取文本时,它也不会获取。我还尝试通过在页面上查找“交易历史”然后单击来单击。那没有用。最后,我想也许页面还没有完全加载,所以我尝试在尝试单击“#tradeHistory_link”之前执行 time.sleep(5) 但无济于事。
这是怎么回事?
首先尝试使用 visibility_of_element_located
预期条件而不是 element_to_be_clickable
。元素并不总是最终在其内部构建内部文本以及它变得可点击的那一刻。可见性通常会稍晚一些。
我还必须提到您的 css 定位器看起来很糟糕。你必须改进它们。
该元素位于 iframe 中,这可能是您无法点击它的原因。在 Selenium 可以与其中的元素交互之前,您需要切换到该框架。在与该元素交互之前,尝试添加此行
driver.switch_to.frame(driver.find_element_by_css_selector('#ms-bond-detail-iframe'))
Trade History
link 出现在 iframe
中。要访问 link,您需要先切换到 iframe
。
使用 WebDriverWait() 并等待 frame_to_be_available_and_switch_to_it() 并使用元素 ID
WebDriverWait(browser,10).until(EC.frame_to_be_available_and_switch_to_it((By.ID,"ms-bond-detail-iframe")))
WebDriverWait(browser,10).until(EC.element_to_be_clickable((By.CSS_SELECTOR,"#tradeHistory_link"))).click()
要退出 iframe,您需要切换到默认内容
browser.switch_to.default_content()
查看下面的代码。我认为除了最后一行,你几乎可以忽略所有内容。
from selenium import webdriver
import os
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import xlsxwriter
from datetime import datetime
import time
chrome_driver = os.path.abspath('C:/Users/ross/Desktop/chromedriver.exe')
browser = webdriver.Chrome(chrome_driver)
browser.get('https://finra-markets.morningstar.com/BondCenter/Default.jsp')
WebDriverWait(browser, 60).until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#TabContainer > div > div.rtq-tab-wrap > div.rtq-tab-menus-wrap > ul > li:nth-child(3) > a > span'))).click()
WebDriverWait(browser, 60).until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#firscreener-cusip'))).send_keys("STWD")
WebDriverWait(browser, 60).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#ms-finra-advanced-search-form > div.ms-finra-advanced-search-btn > input:nth-child(2)"))).click()
WebDriverWait(browser, 60).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#ms-agreement > input"))).click()
WebDriverWait(browser, 60).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#ms-finra-search-results > div > div.qs-resultData > div.qs-resultData-body > div.rtq-grid.rtq-grid-auto-h > div.rtq-grid-hd > div > div:nth-child(7) > div"))).click()
time.sleep(2)
WebDriverWait(browser, 60).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#ms-finra-search-results > div > div.qs-resultData > div.qs-resultData-body > div.rtq-grid.rtq-grid-auto-h > div.rtq-grid-hd > div > div:nth-child(7) > div"))).click()
time.sleep(2)
whole_chart = WebDriverWait(browser, 60).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#ms-finra-search-results > div > div.qs-resultData > div.qs-resultData-body > div.rtq-grid.rtq-grid-auto-h > div.rtq-scrollpanel > div.rtq-grid-scroll"))).text
parent = browser.find_element_by_xpath('//*[@id="ms-finra-search-results"]/div/div[3]/div[1]/div[1]/div[2]/div[2]/div')
count_divs = len(parent.find_elements_by_xpath("./div"))
for row_num in range(1):
symbol = WebDriverWait(browser, 60).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#ms-finra-search-results > div > div.qs-resultData > div.qs-resultData-body > div.rtq-grid.rtq-grid-auto-h > div.rtq-scrollpanel > div.rtq-grid-scroll > div > div:nth-child(" + str(row_num + 1) + ") > div:nth-child(3)"))).text
maturity = WebDriverWait(browser, 60).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#ms-finra-search-results > div > div.qs-resultData > div.qs-resultData-body > div.rtq-grid.rtq-grid-auto-h > div.rtq-scrollpanel > div.rtq-grid-scroll > div > div:nth-child(" + str(row_num + 1) + ") > div:nth-child(7)"))).text
moody_rating = WebDriverWait(browser, 60).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#ms-finra-search-results > div > div.qs-resultData > div.qs-resultData-body > div.rtq-grid.rtq-grid-auto-h > div.rtq-scrollpanel > div.rtq-grid-scroll > div > div:nth-child(" + str(row_num + 1) + ") > div:nth-child(8)"))).text
sandp_rating = WebDriverWait(browser, 60).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#ms-finra-search-results > div > div.qs-resultData > div.qs-resultData-body > div.rtq-grid.rtq-grid-auto-h > div.rtq-scrollpanel > div.rtq-grid-scroll > div > div:nth-child(" + str(row_num + 1) + ") > div:nth-child(9)"))).text
bond_yield = WebDriverWait(browser, 60).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#ms-finra-search-results > div > div.qs-resultData > div.qs-resultData-body > div.rtq-grid.rtq-grid-auto-h > div.rtq-scrollpanel > div.rtq-grid-scroll > div > div:nth-child(" + str(row_num + 1) + ") > div:nth-child(11)"))).text
if symbol.strip() and maturity.strip() and moody_rating.strip() and sandp_rating.strip() and bond_yield.strip() and moody_rating != "WR" and sandp_rating != "NR":
WebDriverWait(browser, 60).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#ms-finra-search-results > div > div.qs-resultData > div.qs-resultData-body > div.rtq-grid.rtq-grid-auto-h > div.rtq-scrollpanel > div.rtq-grid-scroll > div > div:nth-child(" + str(row_num + 1) + ") > div:nth-child(2) > div > a"))).click()
WebDriverWait(browser, 60).until(EC.element_to_be_clickable((By.CSS_SELECTOR,"#tradeHistory_link"))).click()
基本上,我进入了这个页面:https://finra-markets.morningstar.com/BondCenter/BondDetail.jsp?ticker=C724231&symbol=STWD4571190,我希望 Selenium 单击它上面的 'Trade History' link,所以我引用了选择器 '#tradeHistory_link '.出于某种原因,它没有点击,当我尝试只获取文本时,它也不会获取。我还尝试通过在页面上查找“交易历史”然后单击来单击。那没有用。最后,我想也许页面还没有完全加载,所以我尝试在尝试单击“#tradeHistory_link”之前执行 time.sleep(5) 但无济于事。
这是怎么回事?
首先尝试使用 visibility_of_element_located
预期条件而不是 element_to_be_clickable
。元素并不总是最终在其内部构建内部文本以及它变得可点击的那一刻。可见性通常会稍晚一些。
我还必须提到您的 css 定位器看起来很糟糕。你必须改进它们。
该元素位于 iframe 中,这可能是您无法点击它的原因。在 Selenium 可以与其中的元素交互之前,您需要切换到该框架。在与该元素交互之前,尝试添加此行
driver.switch_to.frame(driver.find_element_by_css_selector('#ms-bond-detail-iframe'))
Trade History
link 出现在 iframe
中。要访问 link,您需要先切换到 iframe
。
使用 WebDriverWait() 并等待 frame_to_be_available_and_switch_to_it() 并使用元素 ID
WebDriverWait(browser,10).until(EC.frame_to_be_available_and_switch_to_it((By.ID,"ms-bond-detail-iframe")))
WebDriverWait(browser,10).until(EC.element_to_be_clickable((By.CSS_SELECTOR,"#tradeHistory_link"))).click()
要退出 iframe,您需要切换到默认内容
browser.switch_to.default_content()