社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

如何解析陈旧的元素引用-selenium(python)

Saadiq • 5 年前 • 1538 次点击  

我知道这个问题被问了很多次,但我似乎不能把任何一个决议应用于我自己的情况。

我正在抓取一个网站的某些价值观,然而,价值观存在于网站上的不同配置文件。因此,我登录、检索值、注销、在新配置文件下重新登录、检索值、注销等。

该问题出现在一个悬停菜单项上,该菜单项似乎正在生成过时的元素引用。我想这是因为我注销后又重新登录?这是否可以修复,或者我应该只是启动一个新的webdriver实例?

这是到目前为止我的代码,请记住,我对python很陌生,所以请原谅任何愚蠢的错误或假设:

from selenium import webdriver
from selenium.webdriver.support import ui
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver import ActionChains
from selenium.common.exceptions import StaleElementReferenceException

options = Options()
options.add_argument("start-maximized")
driver = webdriver.Chrome(options=options, executable_path=r'C:/Users/SChogle/Downloads/chromedriver.exe')
actions = ActionChains(driver)

driver.get("xxxxx")

iframe = ui.WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.TAG_NAME, "iframe")))

driver.switch_to.frame(iframe)

driver.find_element_by_id("Username").send_keys("xxxx")
driver.find_element_by_id("Password").send_keys("xxxx")
driver.find_element_by_id("submit_button").click()

driver.switch_to.default_content()

Investment = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "div.menu.menuTopCenter > ul > li:nth-child(3) > a")))
actions.move_to_element(Investment).perform()

Investment_Summary = (WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR,"li:nth-child(3) > div > div:nth-child(1) > a")))).click()

Imp_Prov = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "div#product-UT td.portfolioProductContractFundHeaderValueRight"))).get_attribute('innerHTML').strip()
print(Imp_Prov)

#log-out
log_out = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "a#btnLogoff"))).click()

#log back in

iframe = ui.WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.TAG_NAME, "iframe")))

driver.switch_to.frame(iframe)

driver.find_element_by_id("Username").send_keys("xxxx")
driver.find_element_by_id("Password").send_keys("xxxx")
driver.find_element_by_id("submit_button").click()

driver.switch_to.default_content()

tries = 0
while tries < 3:
    try:
        Investment = WebDriverWait(driver, 10,).until(EC.element_to_be_clickable((By.CSS_SELECTOR,  "div.menu.menuTopCenter > ul > li:nth-child(3) > a")))
        actions.move_to_element(Investment).perform()
        tries = 3

    except StaleElementReferenceException:
        tries += 1

Investment_Summary1 = (WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR,"li:nth-child(3) > div > div:nth-child(1) > a")))).click()

Imp_Pen = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "div#product-UT td.portfolioProductContractFundHeaderValueRight"))).get_attribute('innerHTML').strip()
print(Imp_Pen)

请参阅下面的stacktrace:

174,256,175.68 ZAR
Traceback (most recent call last):
  File "C:/Users/SChogle/PycharmProjects/test1/venv/Web Scraping - BCI.py", line 60, in <module>
    Investment_Summary1 = (WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR,"li:nth-child(3) > div > div:nth-child(1) > a")))).click()
  File "C:\Users\SChogle\PycharmProjects\test1\venv\lib\site-packages\selenium\webdriver\support\wait.py", line 80, in until
    raise TimeoutException(message, screen, stacktrace)
selenium.common.exceptions.TimeoutException: Message: 


Process finished with exit code 1
Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/39776
 
1538 次点击  
文章 [ 2 ]  |  最新文章 5 年前
Dinesh Deshmane
Reply   •   1 楼
Dinesh Deshmane    6 年前

尝试使用-

  1. check元素存在于该位置。
  2. 如果是,则可以使用javascript单击
  3. 如果没有,则再次查找元素并单击。
Guy
Reply   •   2 楼
Guy    6 年前

如果你看看 source code

class element_to_be_clickable(object):
    """ An Expectation for checking an element is visible and enabled such that you can click it."""
    def __init__(self, locator):
        self.locator = locator

    def __call__(self, driver):
        element = visibility_of_element_located(self.locator)(driver)
        if element and element.is_enabled():
            return element
        else:
            return False

这个元素可能以前就过时了 if element and element.is_enabled(): 位于上一行之后( visibility_of_element_located 手柄 StaleElementReferenceException )您可以添加 ignored_exceptions=[StaleElementReferenceException] 减速到 WebDriverWait 解决这个问题

Investment1 = WebDriverWait(driver, 10, ignored_exceptions=[StaleElementReferenceException]).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "div.menu.menuTopCenter > ul > li:nth-child(3) > a")))

还有几点:

  1. 有预期情况 frame_to_be_available_and_switch_to_it 处理框架
  2. python变量应该都是小写的
  3. 你有代码重复,你可以用函数代替

    options = Options()
    options.add_argument("start-maximized")
    driver = webdriver.Chrome(options=options, 
    executable_path=r'C:/Users/SChogle/Downloads/chromedriver.exe')
    actions = ActionChains(driver)
    
    driver.get("xxxxxxx")
    
    def do_login():
        WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it((By.TAG_NAME, "iframe")))
    
        driver.find_element_by_id("Username").send_keys("xxxxx")
        driver.find_element_by_id("Password").send_keys("xxxxx")
        driver.find_element_by_id("submit_button").click()
    
        driver.switch_to.default_content()
    
    def print_content():
        investment = WebDriverWait(driver, 10, ignored_exceptions=[StaleElementReferenceException]).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "div.menu.menuTopCenter > ul > li:nth-child(3) > a")))
        actions.move_to_element(investment).perform()
    
        investment_summary = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR,"li:nth-child(3) > div > div:nth-child(1) > a"))).click()
    
        imp_prov = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "div#product-UT td.portfolioProductContractFundHeaderValueRight"))).get_attribute('innerHTML').strip()
        print(imp_prov)
    
    do_login()
    print_content()
    driver.find_element_by_css_selector("a#btnLogoff").click()
    
    do_login()
    print_content()
    

编辑:

根据您添加的stacktrace,异常实际上是打开的 actions.move_to_element(Investment1).perform() . 它可以通过简单的循环和重试来解决

tries = 0
while tries < 3:
    try:
        investment = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "div.menu.menuTopCenter > ul > li:nth-child(3) > a")))
        actions.move_to_element(investment).perform()
        tries = 3
    except StaleElementReferenceException:
        tries += 1