selenium用法詳解【從入門到實戰】【Python爬蟲】【篇二】
鍵盤控制
webdriver 中 Keys 類幾乎提供了鍵盤上的所有按鍵方法,我們可以使用 send_keys + Keys 實現輸出鍵盤上的組合按鍵如 “Ctrl + C”、“Ctrl + V” 等。
from selenium.webdriver.common.keys import Keys # 定位輸入框并輸入文本 driver.find_element_by_id('xxx').send_keys('Dream丶killer') # 模擬回車鍵進行跳轉(輸入內容后) driver.find_element_by_id('xxx').send_keys(Keys.ENTER) # 使用 Backspace 來刪除一個字符 driver.find_element_by_id('xxx').send_keys(Keys.BACK_SPACE) # Ctrl + A 全選輸入框中內容 driver.find_element_by_id('xxx').send_keys(Keys.CONTROL, 'a') # Ctrl + C 復制輸入框中內容 driver.find_element_by_id('xxx').send_keys(Keys.CONTROL, 'c') # Ctrl + V 粘貼輸入框中內容 driver.find_element_by_id('xxx').send_keys(Keys.CONTROL, 'v')
其他常見鍵盤操作:
設置元素等待
很多頁面都使用 ajax 技術,頁面的元素不是同時被加載出來的,為了防止定位這些尚在加載的元素報錯,可以設置元素等來增加腳本的穩定性。webdriver 中的等待分為 顯式等待 和 隱式等待。
顯式等待
顯式等待:設置一個超時時間,每個一段時間就去檢測一次該元素是否存在,如果存在則執行后續內容,如果超過最大時間(超時時間)則拋出超時異常(TimeoutException)。顯示等待需要使用 WebDriverWait,同時配合 until 或 not until 。下面詳細講解一下。
WebDriverWait(driver, timeout, poll_frequency=0.5, ignored_exceptions=None)
driver:瀏覽器驅動
timeout:超時時間,單位秒
poll_frequency:每次檢測的間隔時間,默認為0.5秒
ignored_exceptions:指定忽略的異常,如果在調用 until 或 until_not 的過程中拋出指定忽略的異常,則不中斷代碼,默認忽略的只有 NoSuchElementException 。
until(method, message=’ ‘)
until_not(method, message=’ ')
method:指定預期條件的判斷方法,在等待期間,每隔一段時間調用該方法,判斷元素是否存在,直到元素出現。until_not 正好相反,當元素消失或指定條件不成立,則繼續執行后續代碼
message: 如果超時,拋出 TimeoutException ,并顯示 message 中的內容
method 中的預期條件判斷方法是由 expected_conditions 提供,下面列舉常用方法。
先定義一個定位器
from selenium.webdriver.common.by import By from selenium import webdriver driver = webdriver.Chrome() locator = (By.ID, 'kw') element = driver.find_element_by_id('kw')
下面寫一個簡單的例子,這里定位一個頁面不存在的元素,拋出的異常信息正是我們指定的內容。
from selenium import webdriver from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By driver = webdriver.Chrome() element = WebDriverWait(driver, 5, 0.5).until( EC.presence_of_element_located((By.ID, 'kw')), message='超時啦!')
隱式等待
隱式等待也是指定一個超時時間,如果超出這個時間指定元素還沒有被加載出來,就會拋出 NoSuchElementException 異常。
除了拋出的異常不同外,還有一點,
隱式等待是全局性的,即運行過程中,如果元素可以定位到,它不會影響代碼運行,但如果定位不到,則它會以輪詢的方式不斷地訪問元素直到元素被找到,若超過指定時間,則拋出異常
。
使用 implicitly_wait() 來實現隱式等待,使用難度相對于顯式等待要簡單很多。
示例:打開個人主頁,設置一個隱式等待時間 5s,通過 id 定位一個不存在的元素,最后打印 拋出的異常 與 運行時間。
from selenium import webdriver from time import time driver = webdriver.Chrome() driver.get('https://blog.csdn.net/qq_43965708') start = time() driver.implicitly_wait(5) try: driver.find_element_by_id('kw') except Exception as e: print(e) print(f'耗時:{time()-start}')
代碼運行到 driver.find_element_by_id('kw') 這句之后觸發隱式等待,在輪詢檢查 5s 后仍然沒有定位到元素,拋出異常。
強制等待
使用 time.sleep() 強制等待,設置固定的休眠時間,對于代碼的運行效率會有影響。以上面的例子作為參照,將 隱式等待 改為 強制等待。
from selenium import webdriver from time import time, sleep driver = webdriver.Chrome() driver.get('https://blog.csdn.net/qq_43965708') start = time() sleep(5) try: driver.find_element_by_id('kw') except Exception as e: print(e) print(f'耗時:{time()-start}')
值得一提的是,對于定位不到元素的時候,從耗時方面隱式等待和強制等待沒什么區別。但如果元素經過 2s 后被加載出來,這時隱式等待就會繼續執行下面的代碼,但 sleep還要繼續等待 3s。
定位一組元素
上篇講述了定位一個元素的 8 種方法,定位一組元素使用的方法只需要將 element 改為 elements 即可,它的使用場景一般是為了批量操作元素。
find_elements_by_id()
find_elements_by_name()
find_elements_by_class_name()
find_elements_by_tag_name()
find_elements_by_xpath()
find_elements_by_css_selector()
find_elements_by_link_text()
find_elements_by_partial_link_text()
這里以 CSDN 首頁的一個 博客專家欄 為例。
下面使用 find_elements_by_xpath 來定位三位專家的名稱。
這是專家名稱部分的頁面代碼,不知各位有沒有想到如何通過 xpath 定位這一組專家的名稱呢?
from selenium import webdriver # 設置無頭瀏覽器 option = webdriver.ChromeOptions() option.add_argument('--headless') driver = webdriver.Chrome(options=option) driver.get('https://blog.csdn.net/') p_list = driver.find_elements_by_xpath("http://p[@class='name']") name = [p.text for p in p_list] name
切換操作
窗口切換
在 selenium 操作頁面的時候,可能會因為點擊某個鏈接而跳轉到一個新的頁面(打開了一個新標簽頁),這時候 selenium 實際還是處于上一個頁面的,需要我們進行切換才能夠定位最新頁面上的元素。
窗口切換需要使用 switch_to.windows() 方法。
首先我們先看看下面的代碼。
代碼流程:先進入 【CSDN首頁】,保存當前頁面的句柄,然后再點擊左側 【CSDN官方博客】跳轉進入新的標簽頁,再次保存頁面的句柄,我們驗證一下 selenium 會不會自動定位到新打開的窗口。
from selenium import webdriver handles = [] driver = webdriver.Chrome() driver.get('https://blog.csdn.net/') # 設置隱式等待 driver.implicitly_wait(3) # 獲取當前窗口的句柄 handles.append(driver.current_window_handle) # 點擊 python,進入分類頁面 driver.find_element_by_xpath('//*[@id="mainContent"]/aside/div[1]/div').click() # 獲取當前窗口的句柄 handles.append(driver.current_window_handle) print(handles) # 獲取當前所有窗口的句柄 print(driver.window_handles)
可以看到第一個列表 handle 是相同的,說明 selenium 實際操作的還是 CSDN首頁 ,并未切換到新頁面。
下面使用 switch_to.windows() 進行切換。
from selenium import webdriver handles = [] driver = webdriver.Chrome() driver.get('https://blog.csdn.net/') # 設置隱式等待 driver.implicitly_wait(3) # 獲取當前窗口的句柄 handles.append(driver.current_window_handle) # 點擊 python,進入分類頁面 driver.find_element_by_xpath('//*[@id="mainContent"]/aside/div[1]/div').click() # 切換窗口 driver.switch_to.window(driver.window_handles[-1]) # 獲取當前窗口的句柄 handles.append(driver.current_window_handle) print(handles) print(driver.window_handles)
上面代碼在點擊跳轉后,使用 switch_to 切換窗口,window_handles 返回的 handle 列表是按照頁面出現時間進行排序的,最新打開的頁面肯定是最后一個,這樣用 driver.window_handles[-1] + switch_to 即可跳轉到最新打開的頁面了。
那如果打開的窗口有多個,如何跳轉到之前打開的窗口,如果確實有這個需求,那么打開窗口是就需要記錄每一個窗口的 key(別名) 與 value(handle),保存到字典中,后續根據 key 來取 handle 。
表單切換
很多頁面也會用帶 frame/iframe 表單嵌套,對于這種內嵌的頁面 selenium 是無法直接定位的,需要使用 switch_to.frame() 方法將當前操作的對象切換成 frame/iframe 內嵌的頁面。
switch_to.frame() 默認可以用的 id 或 name 屬性直接定位,但如果 iframe 沒有 id 或 name ,這時就需要使用 xpath 進行定位。下面先寫一個包含 iframe 的頁面做測試用。
現在我們定位紅框中的 CSDN 按鈕,可以跳轉到 CSDN 首頁。
from selenium import webdriver from pathlib import Path driver = webdriver.Chrome() # 讀取本地html文件 driver.get('file:///' + str(Path(Path.cwd(), 'iframe測試.html'))) # 1.通過id定位 driver.switch_to.frame('CSDN_info') # 2.通過name定位 # driver.switch_to.frame('Dream丶Killer') # 通過xpath定位 # 3.iframe_label = driver.find_element_by_xpath('/html/body/iframe') # driver.switch_to.frame(iframe_label) driver.find_element_by_xpath('//*[@id="csdn-toolbar"]/div/div/div[1]/div/a/img').click()
這里列舉了三種定位方式,都可以定位 iframe 。
Python Selenium
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。