selenium.common.exceptions.ElementNotVisibleException: Message: element not visible Handling method: selenium's handling of drop-down menu events
When using Selenium crawlers, you may encounter some drop-down menus, which are loaded dynamically. If you use the find_element_by_ function directly, an error will be reported, showing selenium.common.exceptions.ElementNotVisibleException: Message: element not visible.
Means element is invisible. So can't get it. At this time, I encountered a problem, how to make the element visible?
At this time, we use ActionChains to simulate the effect
ActionChains(driver).click(driver.find_element(By.ID, 'g-hd-searchs')).perform() #Use perform() to execute action
At this time, you will be surprised to find that the drop-down menu appears successfully.
Next, you can do what you want.
The following introduces ActionChains:
Using selenium for automation, sometimes you need to simulate mouse operations to perform, such as single-click, double-click, right-click, drag and drop, and so on. And selenium provides us with a class to handle such events - ActionChains
selenium.webdriver.common.action_chains.ActionChains(driver)
This class can basically meet all our needs for mouse operation.
1. Basic usage of ActionChains
First of all, you need to understand the execution principle of ActionChains. When you call the method of ActionChains, it will not be executed immediately, but will store all operations in a queue in order. When you call the perform() method, the time in the queue will be Execute in sequence.
In this case we can have two calling methods:
-
chain writing
menu = driver.find_element_by_css_selector(".nav") hidden_submenu = driver.find_element_by_css_selector(".nav #submenu1") ActionChains(driver).move_to_element(menu).click(hidden_submenu).perform()
- step by step
-
menu = driver.find_element_by_css_selector(".nav") hidden_submenu = driver.find_element_by_css_selector(".nav #submenu1") actions = ActionChains(driver) actions.move_to_element(menu) actions.click(hidden_submenu) actions.perform()
-
The essence of the two writing methods is the same, and ActionChains will perform all operations in order.
2.ActionChains method list
click ( on_element=None ) - click the left mouse button
click_and_hold ( on_element=None ) - click the left mouse button without releasing it
context_click ( on_element=None ) - click the right mouse button
double_click ( on_element=None ) - double click the left mouse button
drag_and_drop ( source, target ) - drag to an element and release
drag_and_drop_by_offset ( source, xoffset, yoffset ) - drag to a certain coordinate and release
key_down ( value, element=None ) - press a key on a keyboard
key_up ( value, element=None ) - release a key
move_by_offset ( xoffset , yoffset ) - move the mouse from the current position to a certain coordinate
move_to_element ( to_element ) - move the mouse to an element
move_to_element_with_offset ( to_element, xoffset, yoffset ) - move to a position how far away from an element (coordinates of the upper left corner)
perform () - perform all actions in the chain
release ( on_element=None ) - release the left mouse button at an element position
send_keys ( *keys_to_send ) - send a key to the currently focused element
send_keys_to_element ( element, *keys_to_send ) - send a key to the specified element
Next, an example is used to explain and demonstrate the usage of each method in detail:
3. Code example
1. Click Action
Example URL http://sahitest.com/demo/clicks.htm
Code:
# -*- coding: utf-8 -*-
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains from time import sleep driver = webdriver.Firefox() driver.implicitly_wait(10) driver.maximize_window() driver.get('http://sahitest.com/demo/clicks.htm') click_btn = driver.find_element_by_xpath('//input[@value="click me"]') # 单击按钮 doubleclick_btn = driver.find_element_by_xpath('//input[@value="dbl click me"]') # 双击按钮 rightclick_btn = driver.find_element_by_xpath('//input[@value="right click me"]') # 右键单击按钮 ActionChains(driver).click(click_btn).double_click(doubleclick_btn).context_click(rightclick_btn).perform() # 链式用法 print driver.find_element_by_name('t2').get_attribute('value') sleep(2) driver.quit()
result:
[CLICK][DOUBLE_CLICK][RIGHT_CLICK]
2. Mouse movement
Example URL http://sahitest.com/demo/mouseover.htm
Sample code:
# -*- coding: utf-8 -*-
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains from time import sleep driver = webdriver.Firefox() driver.implicitly_wait(10) driver.maximize_window() driver.get('http://sahitest.com/demo/mouseover.htm') write = driver.find_element_by_xpath('//input[@value="Write on hover"]') # 鼠标移动到此元素,在下面的input框中会显示“Mouse moved” blank = driver.find_element_by_xpath('//input[@value="Blank on hover"]') # 鼠标移动到此元素,会清空下面input框中的内容 result = driver.find_element_by_name('t1') action = ActionChains(driver) action.move_to_element(write).perform() # 移动到write,显示“Mouse moved” print result.get_attribute('value') # action.move_to_element(blank).perform() action.move_by_offset(10, 50).perform() # 移动到距离当前位置(10,50)的点,与上句效果相同,移动到blank上,清空 print result.get_attribute('value') action.move_to_element_with_offset(blank, 10, -40).perform() # 移动到距离blank元素(10,-40)的点,可移动到write上 print result.get_attribute('value') sleep(2) driver.quit()
result
Mouse moved
Mouse moved
Generally, the position relationship is rarely used to move the mouse. If necessary, you can refer to the following link to measure the position of the element
http://jingyan.baidu.com/article/eb9f7b6d87e2ae869264e847.html
3. Drag and drop
Example URL http://sahitest.com/demo/dragDropMooTools.htm
Code:
# -*- coding: utf-8 -*-
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains from time import sleep driver = webdriver.Firefox() driver.implicitly_wait(10) driver.maximize_window() driver.get('http://sahitest.com/demo/dragDropMooTools.htm') dragger = driver.find_element_by_id('dragger') # 被拖拽元素 item1 = driver.find_element_by_xpath('//div[text()="Item 1"]') # 目标元素1 item2 = driver.find_element_by_xpath('//div[text()="Item 2"]') # 目标2 item3 = driver.find_element_by_xpath('//div[text()="Item 3"]') # 目标3 item4 = driver.find_element_by_xpath('//div[text()="Item 4"]') # 目标4 action = ActionChains(driver) action.drag_and_drop(dragger, item1).perform() # 1.移动dragger到目标1 sleep(2) action.click_and_hold(dragger).release(item2).perform() # 2.效果与上句相同,也能起到移动效果 sleep(2) action.click_and_hold(dragger).move_to_element(item3).release().perform() # 3.效果与上两句相同,也能起到移动的效果 sleep(2) # action.drag_and_drop_by_offset(dragger, 400, 150).perform() # 4.移动到指定坐标 action.click_and_hold(dragger).move_by_offset(400, 150).release().perform() # 5.与上一句相同,移动到指定坐标 sleep(2) driver.quit()
result:
dropped dropped dropped dropped
Generally, coordinate positioning is rarely used. It is enough to use method 1 in the above example. If you look at the source code, you will find that method 2 is actually the implementation of drag_and_drop() in method 1. Note: Pay attention to adding waiting time when dragging, sometimes it will fail because the speed is too fast.
4. Button
There are many ways to simulate keys, which can be implemented by win32api, by SendKeys, or by the send_keys() method of selenium's WebElement object. The ActionChains class also provides several methods for simulating keys.
Example URL http://sahitest.com/demo/keypress.htm
Code 1:
# -*- coding: utf-8 -*-
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains from time import sleep driver = webdriver.Firefox() driver.implicitly_wait(10) driver.maximize_window() driver.get('http://sahitest.com/demo/keypress.htm') key_up_radio = driver.find_element_by_id('r1') # 监测按键升起 key_down_radio = driver.find_element_by_id('r2') # 监测按键按下 key_press_radio = driver.find_element_by_id('r3') # 监测按键按下升起 enter = driver.find_elements_by_xpath('//form[@name="f1"]/input')[1] # 输入框 result = driver.find_elements_by_xpath('//form[@name="f1"]/input')[0] # 监测结果 # 监测key_down key_down_radio.click() ActionChains(driver).key_down(Keys.CONTROL, enter).key_up(Keys.CONTROL).perform() print result.get_attribute('value') # 监测key_up key_up_radio.click() enter.click() ActionChains(driver).key_down(Keys.SHIFT).key_up(Keys.SHIFT).perform() print result.get_attribute('value') # 监测key_press key_press_radio.click() enter.click() ActionChains(driver).send_keys('a').perform() print result.get_attribute('value') driver.quit()
result:
key downed charCode=[0] keyCode=[17] CTRL
key upped charCode=[0] keyCode=[16] NONE key pressed charCode=[97] keyCode=[0] NONE
Example 2:
Example URL http://sahitest.com/demo/label.htm
Code:
# -*- coding: utf-8 -*-
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains from selenium.webdriver.common.keys import Keys from time import sleep driver = webdriver.Firefox() driver.implicitly_wait(10) driver.maximize_window() driver.get('http://sahitest.com/demo/label.htm') input1 = driver.find_elements_by_tag_name('input')[3] input2 = driver.find_elements_by_tag_name('input')[4] action = ActionChains(driver) input1.click() action.send_keys('Test Keys').perform() action.key_down(Keys.CONTROL).send_keys('a').key_up(Keys.CONTROL).perform() # ctrl+a action.key_down(Keys.CONTROL).send_keys('c').key_up(Keys.CONTROL).perform() # ctrl+c action.key_down(Keys.CONTROL, input2).send_keys('v').key_up(Keys.CONTROL).perform() # ctrl+v print input1.get_attribute('value') print input2.get_attribute('value') driver.quit()
result:
Test Keys
Test Keys
Copy and paste can also be achieved with WebElement<input>.send_keys(). You can try it, or you can use a lower-level method. It is also one of the ways to deal with the os pop-up box, win32api. If you are interested, you can also try SendKeys, keybd_event
When using Selenium crawlers, you may encounter some drop-down menus, which are loaded dynamically. If you use the find_element_by_ function directly, an error will be reported, showing selenium.common.exceptions.ElementNotVisibleException: Message: element not visible.
Means element is invisible. So can't get it. At this time, I encountered a problem, how to make the element visible?
At this time, we use ActionChains to simulate the effect
ActionChains(driver).click(driver.find_element(By.ID, 'g-hd-searchs')).perform() #Use perform() to execute action
At this time, you will be surprised to find that the drop-down menu appears successfully.
Next, you can do what you want.
The following introduces ActionChains:
Using selenium for automation, sometimes you need to simulate mouse operations to perform, such as single-click, double-click, right-click, drag and drop, and so on. And selenium provides us with a class to handle such events - ActionChains
selenium.webdriver.common.action_chains.ActionChains(driver)
This class can basically meet all our needs for mouse operation.
1. Basic usage of ActionChains
First of all, you need to understand the execution principle of ActionChains. When you call the method of ActionChains, it will not be executed immediately, but will store all operations in a queue in order. When you call the perform() method, the time in the queue will be Execute in sequence.
In this case we can have two calling methods:
-
chain writing
menu = driver.find_element_by_css_selector(".nav") hidden_submenu = driver.find_element_by_css_selector(".nav #submenu1") ActionChains(driver).move_to_element(menu).click(hidden_submenu).perform()
- step by step
-
menu = driver.find_element_by_css_selector(".nav") hidden_submenu = driver.find_element_by_css_selector(".nav #submenu1") actions = ActionChains(driver) actions.move_to_element(menu) actions.click(hidden_submenu) actions.perform()
-
The essence of the two writing methods is the same, and ActionChains will perform all operations in order.
2.ActionChains method list
click ( on_element=None ) - click the left mouse button
click_and_hold ( on_element=None ) - click the left mouse button without releasing it
context_click ( on_element=None ) - click the right mouse button
double_click ( on_element=None ) - double click the left mouse button
drag_and_drop ( source, target ) - drag to an element and release
drag_and_drop_by_offset ( source, xoffset, yoffset ) - drag to a certain coordinate and release
key_down ( value, element=None ) - press a key on a keyboard
key_up ( value, element=None ) - release a key
move_by_offset ( xoffset , yoffset ) - move the mouse from the current position to a certain coordinate
move_to_element ( to_element ) - move the mouse to an element
move_to_element_with_offset ( to_element, xoffset, yoffset ) - move to a position how far away from an element (coordinates of the upper left corner)
perform () - perform all actions in the chain
release ( on_element=None ) - release the left mouse button at an element position
send_keys ( *keys_to_send ) - send a key to the currently focused element
send_keys_to_element ( element, *keys_to_send ) - send a key to the specified element
Next, an example is used to explain and demonstrate the usage of each method in detail:
3. Code example
1. Click Action
Example URL http://sahitest.com/demo/clicks.htm
Code:
# -*- coding: utf-8 -*-
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains from time import sleep driver = webdriver.Firefox() driver.implicitly_wait(10) driver.maximize_window() driver.get('http://sahitest.com/demo/clicks.htm') click_btn = driver.find_element_by_xpath('//input[@value="click me"]') # 单击按钮 doubleclick_btn = driver.find_element_by_xpath('//input[@value="dbl click me"]') # 双击按钮 rightclick_btn = driver.find_element_by_xpath('//input[@value="right click me"]') # 右键单击按钮 ActionChains(driver).click(click_btn).double_click(doubleclick_btn).context_click(rightclick_btn).perform() # 链式用法 print driver.find_element_by_name('t2').get_attribute('value') sleep(2) driver.quit()
result:
[CLICK][DOUBLE_CLICK][RIGHT_CLICK]
2. Mouse movement
Example URL http://sahitest.com/demo/mouseover.htm
Sample code:
# -*- coding: utf-8 -*-
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains from time import sleep driver = webdriver.Firefox() driver.implicitly_wait(10) driver.maximize_window() driver.get('http://sahitest.com/demo/mouseover.htm') write = driver.find_element_by_xpath('//input[@value="Write on hover"]') # 鼠标移动到此元素,在下面的input框中会显示“Mouse moved” blank = driver.find_element_by_xpath('//input[@value="Blank on hover"]') # 鼠标移动到此元素,会清空下面input框中的内容 result = driver.find_element_by_name('t1') action = ActionChains(driver) action.move_to_element(write).perform() # 移动到write,显示“Mouse moved” print result.get_attribute('value') # action.move_to_element(blank).perform() action.move_by_offset(10, 50).perform() # 移动到距离当前位置(10,50)的点,与上句效果相同,移动到blank上,清空 print result.get_attribute('value') action.move_to_element_with_offset(blank, 10, -40).perform() # 移动到距离blank元素(10,-40)的点,可移动到write上 print result.get_attribute('value') sleep(2) driver.quit()
result
Mouse moved
Mouse moved
Generally, the position relationship is rarely used to move the mouse. If necessary, you can refer to the following link to measure the position of the element
http://jingyan.baidu.com/article/eb9f7b6d87e2ae869264e847.html
3. Drag and drop
Example URL http://sahitest.com/demo/dragDropMooTools.htm
Code:
# -*- coding: utf-8 -*-
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains from time import sleep driver = webdriver.Firefox() driver.implicitly_wait(10) driver.maximize_window() driver.get('http://sahitest.com/demo/dragDropMooTools.htm') dragger = driver.find_element_by_id('dragger') # 被拖拽元素 item1 = driver.find_element_by_xpath('//div[text()="Item 1"]') # 目标元素1 item2 = driver.find_element_by_xpath('//div[text()="Item 2"]') # 目标2 item3 = driver.find_element_by_xpath('//div[text()="Item 3"]') # 目标3 item4 = driver.find_element_by_xpath('//div[text()="Item 4"]') # 目标4 action = ActionChains(driver) action.drag_and_drop(dragger, item1).perform() # 1.移动dragger到目标1 sleep(2) action.click_and_hold(dragger).release(item2).perform() # 2.效果与上句相同,也能起到移动效果 sleep(2) action.click_and_hold(dragger).move_to_element(item3).release().perform() # 3.效果与上两句相同,也能起到移动的效果 sleep(2) # action.drag_and_drop_by_offset(dragger, 400, 150).perform() # 4.移动到指定坐标 action.click_and_hold(dragger).move_by_offset(400, 150).release().perform() # 5.与上一句相同,移动到指定坐标 sleep(2) driver.quit()
result:
dropped dropped dropped dropped
Generally, coordinate positioning is rarely used. It is enough to use method 1 in the above example. If you look at the source code, you will find that method 2 is actually the implementation of drag_and_drop() in method 1. Note: Pay attention to adding waiting time when dragging, sometimes it will fail because the speed is too fast.
4. Button
There are many ways to simulate keys, which can be implemented by win32api, by SendKeys, or by the send_keys() method of selenium's WebElement object. The ActionChains class also provides several methods for simulating keys.
Example URL http://sahitest.com/demo/keypress.htm
Code 1:
# -*- coding: utf-8 -*-
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains from time import sleep driver = webdriver.Firefox() driver.implicitly_wait(10) driver.maximize_window() driver.get('http://sahitest.com/demo/keypress.htm') key_up_radio = driver.find_element_by_id('r1') # 监测按键升起 key_down_radio = driver.find_element_by_id('r2') # 监测按键按下 key_press_radio = driver.find_element_by_id('r3') # 监测按键按下升起 enter = driver.find_elements_by_xpath('//form[@name="f1"]/input')[1] # 输入框 result = driver.find_elements_by_xpath('//form[@name="f1"]/input')[0] # 监测结果 # 监测key_down key_down_radio.click() ActionChains(driver).key_down(Keys.CONTROL, enter).key_up(Keys.CONTROL).perform() print result.get_attribute('value') # 监测key_up key_up_radio.click() enter.click() ActionChains(driver).key_down(Keys.SHIFT).key_up(Keys.SHIFT).perform() print result.get_attribute('value') # 监测key_press key_press_radio.click() enter.click() ActionChains(driver).send_keys('a').perform() print result.get_attribute('value') driver.quit()
result:
key downed charCode=[0] keyCode=[17] CTRL
key upped charCode=[0] keyCode=[16] NONE key pressed charCode=[97] keyCode=[0] NONE
Example 2:
Example URL http://sahitest.com/demo/label.htm
Code:
# -*- coding: utf-8 -*-
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains from selenium.webdriver.common.keys import Keys from time import sleep driver = webdriver.Firefox() driver.implicitly_wait(10) driver.maximize_window() driver.get('http://sahitest.com/demo/label.htm') input1 = driver.find_elements_by_tag_name('input')[3] input2 = driver.find_elements_by_tag_name('input')[4] action = ActionChains(driver) input1.click() action.send_keys('Test Keys').perform() action.key_down(Keys.CONTROL).send_keys('a').key_up(Keys.CONTROL).perform() # ctrl+a action.key_down(Keys.CONTROL).send_keys('c').key_up(Keys.CONTROL).perform() # ctrl+c action.key_down(Keys.CONTROL, input2).send_keys('v').key_up(Keys.CONTROL).perform() # ctrl+v print input1.get_attribute('value') print input2.get_attribute('value') driver.quit()
result:
Test Keys
Test Keys
Copy and paste can also be achieved with WebElement<input>.send_keys(). You can try it, or you can use a lower-level method. It is also one of the ways to deal with the os pop-up box, win32api. If you are interested, you can also try SendKeys, keybd_event