我正在尝试废弃一个内容(divs(每2秒刷新一次的网站。
我当前的代码工作正常,除了我不断得到StaleElementReferenceException
因为元素不断刷新所有内容 2 秒。
以下是我到目前为止所拥有的
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.chrome.options import Options
import time, sys
option = webdriver.ChromeOptions()
browser = webdriver.Chrome(executable_path='chromedriver', chrome_options=option)
browser.get("example.com")
sports_categories = browser.find_elements_by_css_selector('div.sidebar-wrapper')
for sport in sports_categories:
if sport.text == 'FOOTBALL':
sport.click()
time.sleep(2)
sub_menus_html = browser.find_element_by_css_selector('div.category.lvl1.open div.dropdown')
print(sub_menus_html)
我的问题是,
我- 如何处理这种情况,以便即使div 在后台刷新,我也有确切的目标内容
任何帮助或建议将不胜感激。
由于您的click()
正在刷新元素,因此您必须在DOM中收集当前元素,因为在开始循环之前收集的元素列表已变为STALE。
下面是一个示例,说明如何循环并不断更新要循环的元素的列表对象:
option = webdriver.ChromeOptions()
browser = webdriver.Chrome(executable_path='chromedriver', chrome_options=option)
browser.get("example.com")
sports_categories = browser.find_elements_by_css_selector('div.sidebar-wrapper')
# add counter to keep track
counter = 0
for sport in sports_categories:
#add category refresh here
current_categories= browser.find_elements_by_css_selector('div.sidebar-wrapper')
if current_categories[counter].text == 'FOOTBALL':
current_categories[counter].click()
# I would recommend using something other than sleep to wait for load
# like webdriverwait conditions combined with Expected Conditions
time.sleep(2)
sub_menus_html = browser.find_element_by_css_selector('div.category.lvl1.open div.dropdown')
print(sub_menus_html)
counter += 1
由于我无法访问您正在访问的网站,因此我不确定此确切的代码块是否会按原样工作。
如果div.sidebar-wrapper
中项目的长度发生变化,或者该边栏中的项目顺序发生变化,则可能会遇到问题。
但是,刷新您循环使用的元素列表背后的逻辑仍然成立。
我不确定如何在Python API中做到这一点,但是在NodeJS WebDriver API中,您可以waitForVisible
特定的XPath
选择器,然后单击它。 在您的情况下,选择器可以是:
//div[contains(@class, 'sidebar-wrapper')][text() = 'FOOTBALL']