當你需要執行復雜的操作時,比如將一個元素按住拖動到另一個元素上去,需要移動鼠標然后點擊并按下鍵盤某個按鍵等等。
當然,在 Web 頁面上,這種操作好像比較少。
但是,如果遇到了怎么辦呢?這就需要用到 ActionChains 這個類啦。
ActionChains 提供了對動作的鏈式操作,也就是可以生成一個操作的隊列,將復雜的操作過程分解成單個操作,然后組合起來一次性執行。
這里面主要是鼠標操作,加上一些鍵盤操作。
以簡單的鼠標移動為例,京東首頁上的商品二級分類默認處于隱藏狀態,需要將鼠標移動到一級分類上才會顯示。
我們可以模擬鼠標移動,到元素上然后再點擊二級菜單,比如我們先點擊家用電器,再點擊超薄電視。
# 兩種寫法,一種是直接鏈式調用,另一種分別調用
# 直接鏈式調用
from selenium.webdriver import ActionChains
# ... 省略打開過程
e = driver.find_element_by_link_text("家用電器")
# 將鼠標懸停在家用電器上,暫停0.1s
ActionChains(driver).move_to_element(e).pause(0.1).perform()
# 第二種
action = ActionChains(driver)
action.move_to_element(e)
action.pause(0.1)
action.perform()
無論哪種方式,動作都是按照它們被調用的順序執行。
通過 ActionChains 的對象生成操作隊列,在沒有執行提交 perform() 之前,所有操作只是暫存于隊列中,不會實際在頁面上操作,需要執行 perform() 時才會實際執行操作。
除了上面的鼠標懸停 move_to_element 操作外,還有其他的一些操作:
鼠標懸停
1. move_by_offset(xoffset, yoffset) 鼠標移動偏移量
ActionChains(driver).move_by_offset(100, 100).perform()
偏移量: 從當前位置增加和減少的坐標值, 正數為增加,負數為減少。
從當前鼠標位置向右下移動,假設當前位置為(300,500),則移動到(400, 600)。
2. move_to_element(to_element)鼠標移動到指定元素
e = driver.find_element_by_id('su')
ActionChains(driver).move_to_element(e).perform()
3. move_to_element_with_offset(to_element, xoffset, yoffset) 將鼠標移動到基于元素的偏移量,偏移量基于鼠標左上角的坐標點
e = driver.find_element_by_id('su')
ActionChains(driver).move_to_element_with_offset(e, 100, 100).perform()
移動到 id 為 su 的元素右下方。
鼠標點擊
1. click(on_element=None) 點擊指定元素,如果沒有指定元素,則點擊當前鼠標所在位置
e = driver.find_element_by_id('su')
ActionChains(driver).click(e).perform()
2. double_click(on_element=None) 雙擊元素,如果沒有指定元素則在當前鼠標位置雙擊
e = driver.find_element_by_id('su')
ActionChains(driver).double_click(e).perform()
3. context_click(on_element=None) 在元素上點擊鼠標右鍵,如果沒有指定則在當前鼠標位置單擊右鍵
e = driver.find_element_by_id('su')
ActionChains(driver).context_click(e).perform()
4. click_and_hold(on_element=None) 鼠標按下不松
e = driver.find_element_by_id('su')
ActionChains(driver).click_and_hold(e).perform()
注意,此時鼠標一直處于按下狀態,直到執行 release() 釋放鼠標的操作。
拖動元素
這類操作相當于是鼠標按住某個元素,然后移動鼠標,實現對元素的拖動操作。當然前提是你操作的元素要能夠支持拖動。
1. drag_and_drop(source, target) 在 source 元素上按下鼠標左鍵,并拖動到 target 元素并松開鼠標
e1 = driver.find_element_by_id('source')
e2 = driver.find_element_by_id('target')
ActionChains(driver).drag_and_drop(e1, e2).perform()
按住 e1 元素,拖動到 e2 元素。
2. drag_and_drop_by_offset(source, xoffset, yoffset) 在source元素上按下鼠標左鍵,并按偏移量拖動
e = driver.find_element_by_id('source')
ActionChains(driver).drag_and_drop_by_offset(e, -100, -100).perform()
從 e 元素的位置向左上角移動。
鍵盤操作
1. send_keys(*keys_to_send)
在當前焦點元素發送按鍵
ActionChains(driver).send_keys('手機').perform()
2. send_keys_to_element(self, element, *keys_to_send)
向指定元素發送按鍵
e = driver.find_element_by_id('kw')
ActionChains(driver).send_keys_to_element(e, '測試').perform()
3. key_down(value, element=None) 按下一個特殊按鍵
只能用于 Ctrl, Alt,Shift 鍵,注意此時按鍵只是按下并沒有松開,用于進行按鍵組合操作,如 Ctrl+A。
4. key_up( value, element=None) 釋放一個按下的鍵
與 key_down() 配套使用,用于釋放一個已按下的按鍵,只能用于 Ctrl, Alt,Shift 鍵
如果要發送組合鍵,要這么寫:
ActionChains(driver).key_down(Keys.CONTROL) \
.send_keys('c').key_up(Keys.CONTROL).perform()
隊列操作
1. perform() 提交隊列中的所有操作
所有操作都需要通過 perform() 才會實際提交到瀏覽器。
2. rest_actions() 清空隊列中的操作
將隊列中已存儲的操作清空。
3. pause(seconds) 暫停所有動作
相當于等待,用于鏈式操作過程中的等待。
4. release(on_element=None) 松開按下的鼠標
如果有鼠標按下的操作,那么需要通過 release() 釋放鼠標。