[Repost]Selenium ElementNotVisibleException: Cannot click on element

Problem Statement


I am using the Selenium WebDriver to clickon a menu item which is not visible until you hover over a toplevel menu, and when I invoke the Click method on the IWebElement,an ElementNotVisibleException is thrown with the message of Cannotclick on element.

The problem is that I have made the IWebElement visible by hoveringover the top level menu.  It is, in fact,absolutely visible, thus this exception should not bethrown.  The Click method works just fine on otherelements which are not hidden until the user hovers over themenu.

As an aside, here is the code I used to hover over the topmenu:

 1: var womensShoesMenu = this.webDriver.FindElement(By.CssSelector("a.topNavLink[href='/Womens-Shoe-Store']"));
 2: var builder = new Actions(this.webDriver);
 3: builder.MoveToElement(womensShoesMenu).Build().Perform();
 4:  

This is the code I used to invoke the Click method:
 1: var wait = new WebDriverWait(this.webDriver, TimeSpan.FromSeconds(5));
 2: var womensBoots = wait.Until((p) => this.webDriver.FindElement(By.CssSelector("#topNavigation ul div.menuItem a[href='/Womens-Boots']")));
 3: womensBoots.Click();
 4:  
 
I figured using the Wait code would fix the problem with the linknot being visible, assuming the code is simply executing tooquickly or something.  The debugger shows that theweb element is definitely visible, so, what isgoing?  I can definitively say that it beats thehell out of me; for now, I’m chalking this up to a bug withSelenium WebDriver.  Fortunately, however, I founda solution to the problem.

Solution

Instead of calling the Click method on the Selenium IWebElementobject, I used JavaScript instead.  This workslike a champ, and so far, appears to be reliable.

 1: var womensBoots = this.webDriver.FindElement(By.CssSelector("#topNavigation ul div.menuItem a[href='/Womens-Boots']"));
 2: ((IJavaScriptExecutor)this.webDriver).ExecuteScript("arguments[0].click();", womensBoots);
 3:  

 

Updated Solution

I’m adding a second solution after posting thisarticle.  It turns out that the Click method ofIWebElement works just fine in my scenario above; I simply wasn’tusing the WebDriverWait class correctly.  I reallyjust needed to have the browser wait for 1 second after performingthe hover on the top menu, and then all of the drivers I wastesting (Firefox, Internet Explorer, and Chrome) workedgreat.  Here is the updated code:

private static void DoWait(int milliseconds)
{
    var wait = new WebDriverWait(webDriver, TimeSpan.FromMilliseconds(milliseconds));
    var waitComplete = wait.Until<<span style="color: rgb(0, 0, 255);">bool>(
        arg =>
            {
                System.Threading.Thread.Sleep(milliseconds);
                return true;
            });
}
var womensBoots = webDriver.FindElement(By.CssSelector("#topNavigation ul div.menuItem a[href='/Womens-Boots']"));
DoWait(1000);
womensBoots.Click();
((IJavaScriptExecutor)webDriver).ExecuteScript("arguments[0].click();", womensBoots);

 

Discussion

I’m new to Selenium, only having started using it as a developer afew days ago, so it is very likely I’m simply doing this wrong andI honestly have no idea of the problem I’m encountering is a bug ornot.  I’ve read similar posts about this, so itseems to be a bug, but as I dig deeper into the system I’ll learnmore.  Since Selenium is open source, if I get thetime, perhaps I’ll even go spelunking into the code to find out andmaybe even attempt to fix it!

import re import json import time import requests import datetime import pymysql import selenium from bs4 import BeautifulSoup from selenium import webdriver from selenium.webdriver.support.ui import WebDriverWait from sqlalchemy import create_engine, Column, Integer, String, Text, DateTime from sqlalchemy.orm import sessionmaker from sqlalchemy.ext.declarative import declarative_base from selenium.webdriver import Edge, EdgeOptions # 创建浏览器对象 options = EdgeOptions() options.use_chromium = True options.binary_location = r'C:\Users\邓枫林\PycharmProjects\pythonProject\edgedriver_win64\msedgedriver.exe' browser = Edge(options=options) wait = WebDriverWait(browser, 10) # 打开微博话题页面 url = 'https://weibo.com/n/%E4%B8%AD%E5%9B%BD%E9%A3%9F%E5%93%81%E5%8D%AB%E7%94%9F?from=feed&loc=at&nick=%E4%B8%AD%E5%9B%BD%E9%A3%9F%E5%93%81%E5%8D%AB%E7%94%9F&order=hot' browser.get(url) # 等待页面加载完成 wait.until(lambda driver: driver.execute_script("return document.readyState") == "complete") browser = selenium.webdriver.Edge(executable_path='C:/Users/邓枫林/PycharmProjects/pythonProject/edgedriver_win64/msedgedriver.exe') wait = selenium.webdriver.support.ui.WebDriverWait(browser, 10) # 监测页面是否包含“高校类”敏感词汇 if '高校类' in browser.page_source: # 获取原始微博 weibo = browser.find_element_by_css_selector('.WB_feed_detail .WB_text.W_f14').text # 获取转发该微博的用户昵称和转发内容 reposts = [] repost_items = browser.find_elements_by_css_selector('.list_ul .list_li') for item in repost_items: nickname = item.find_element_by_css_selector('.WB_text.W_f14').text content = item.find_element_by_css_selector('.WB_text.W_f14 + .comment_txt').text reposts.append({'nickname': nickname, 'content': content}) # 关闭浏览器 browser.quit() # 将微博和转发内容存入MySQL数据库中 Base = declarative_base() class Weibo(Base): tablename = 'weibo_user' id = Column(Integer, primary_key=True) content = Column(Text) create_time = Column(DateTime) class Repost(Base): tablename = 'weibo_repost' id = Column(Integer, primary_key=True) weibo_id = Column(Integer) nickname = Column(String(50)) content = Column(Text) engine = create_engine('mysql+pymysql://root:root@hostname:port/weibo?charset=utf8mb4') Session = sessionmaker(bind=engine) session = Session() now = datetime.datetime.now() weibo_obj = Weibo(content=weibo, create_time=now) session.add(weibo_obj) session.commit() for repost in reposts: repost_obj = Repost(weibo_id=weibo_obj.id, nickname=repost['nickname'], content=repost['content']) session.add(repost_obj) session.commit() session.close() else: # 关闭浏览器 browser.quit()
最新发布
06-12
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值