Selenium是一個Web的自動化測試工具,最初是為網站自動化測試而開發的,可以按指定的命令自動操作,但是他需要與第三方瀏覽器結合在一起才能使用。如果我們把 Selenium和第三方瀏覽器(比如Chrome)結合在一起,就可以執行一個非常強大的網路爬蟲了,這個爬蟲可以處理 JavaScrip、Cookie、headers,以及任何我們真實使用者需要做的事情。
一、安裝
sudo pip3 install selenium
二、快速入門
from selenium import webdriver # 匯入webdriver from selenium.webdriver.common.keys import Keys #Keys`類提供鍵盤按鍵的支援,比如:RETURN, F1, ALT等 from selenium.webdriver.chrome.options import Options #匯入Chrome瀏覽器配置選項類
options = Options() options.add_argument('--headless')#無介面瀏覽器 options.add_argument('--disable-gpu')# 禁用gpu加速,規避bug driver = webdriver.Chrome(options=options) #建立瀏覽器物件 driver.get("https://www.baidu.com/") # get方法會開啟一個頁面 driver.implicitly_wait(10) # 通常開啟頁面後會等待一會,讓頁面載入 print (driver.title) # 列印頁面標題 "百度一下,你就知道" driver.save_screenshot("baidu.png") # 生成當前頁面快照並儲存 elem = driver.find_element_by_id('kw') #根據id查詢元素 elem.clear() #清空搜尋框 elem.send_keys('中國') #搜尋中國 elem.send_keys(Keys.RETURN) #按Enter鍵 print(driver.page_source) # 列印網頁渲染後的原始碼 print(driver.get_cookies()) # 獲取當前頁面Cookie print(driver.current_url) # 獲取當前url # driver.close() 關閉當前頁面,如果只有一個頁面,會關閉瀏覽器 driver.quit() # 關閉瀏覽器
三、查詢元素
-
查詢單個元素(如果有多個匹配的元素,則返回第一個匹配到的元素)
-
find_element_by_id 通過id查詢
login_form = driver.find_element_by_id('loginForm')
-
find_element_by_name 通過name查詢
username = driver.find_element_by_name('username') password = driver.find_element_by_name('password')
-
find_element_by_xpath 通過xpath查詢
login_form = driver.find_element_by_xpath("//form[@id='loginForm']")
-
find_element_by_link_text 通過連結文字獲取超連結元素
continue_link = driver.find_element_by_link_text('Continue')
-
find_element_by_partial_link_text 通過部分連結文字獲取超連結元素
continue_link = driver.find_element_by_partial_link_text('Conti')
-
find_element_by_tag_name 通過標籤名查詢
heading1 = driver.find_element_by_tag_name('h1')
-
find_element_by_class_name 通過類名查詢
content = driver.find_element_by_class_name('content')
-
find_element_by_css_selector 通過css選擇器查詢
content = driver.find_element_by_css_selector('p.content')
-
-
一次查詢多個元素(返回的是元素列表)
-
find_elements_by_name
-
find_elements_by_xpath
-
find_elements_by_link_text
-
find_elements_by_partial_link_text
-
find_elements_by_tag_name
-
find_elements_by_class_name
-
find_elements_by_css_selector
-
-
此外還有兩個私有方法find_element和find_elements
from selenium.webdriver.common.by import By driver.find_element(By.XPATH, '//button[text()="Some text"]') driver.find_elements(By.XPATH, '//button')
By類的其他屬性還包括:
ID = "id" XPATH = "xpath" LINK_TEXT = "link text" PARTIAL_LINK_TEXT = "partial link text" NAME = "name" TAG_NAME = "tag name" CLASS_NAME = "class name" CSS_SELECTOR = "css selector"
四、滑鼠動作鏈
有些時候,我們需要再頁面上模擬一些滑鼠操作,比如雙擊、右擊、拖拽甚至按住不動等,我們可以通過匯入ActionChains 類來做到。
-
匯入ActionChains類
from selenium.webdriver import ActionChains
-
一般樣式
ActionChains(driver).操作方法1.操作方法2.....perform()
ActionChains物件上的操作方法儲存在物件的佇列中,在呼叫perform()方法時,才會按照佇列中的順序去觸發操作
-
常見方法
-
click(on_element=None)
- 單擊元素。如果沒有傳入引數,則在當前滑鼠位置進行操作
-
click_and_hold(on_element=None)
- 在元素上單擊滑鼠左鍵並按住不放。如果沒有傳入引數,則在當前滑鼠位置進行操作
-
context_click(on_element=None)
- 在元素上進行右擊。如果沒有傳入引數,則在當前滑鼠位置進行操作
-
double_click(on_element=None)
- 在元素上進行雙擊。如果沒有傳入引數,則在當前滑鼠位置進行操作
-
drag_and_drop(source,target)
- 在起始元素上按住滑鼠左鍵,並拖動到目標元素上進行釋放
-
drag_and_drop_by_offset(source,xoffset,yoffset)
- 滑鼠點選元素,並按住偏移量進行拖放
-
move_by_offset(xoffset,yoffset)
- 滑鼠從當前位置按照偏移量進行移動
-
move_to_element(to_element)
- 滑鼠移動到元素中間位置
-
五、頁面下拉框處理
我們已經知道了怎樣向文字框中輸入文字,但是有時候我們會碰到<select> </select>
標籤的下拉框。直接點選下拉框中的選項不一定可行。
-
WebDriver的支援類包括一個叫做 Select的類,他提供有用的方法處理這些內容:
from selenium.webdriver.support.ui import Select select = Select(driver.find_element_by_name('name')) select.select_by_index(index) #index索引從0開始 select.select_by_visible_text("text") #text是在option標籤文字的值,是顯示在下拉框的值 select.select_by_value(value) #value是option標籤的一個屬性值,並不是顯示在下拉框中的值
-
取消選擇
select.deselect_all()
六、彈窗處理
Selenium WebDriver 內建了對處理彈出對話方塊的支援。在你的某些動作之後可能會觸發彈出對話方塊,你可以像下面這樣訪問對話方塊:
alert = driver.switch_to.alert() # 切換進alert print(alert.text())# 列印alert文字內容 alert.accept()# 關閉彈框(接受) # alert.dismiss() 關閉彈窗(拒絕) # alert.send_keys('selenium') 向彈窗裡輸入內容
七、頁面切換
瀏覽器一般會開啟多個視窗,切換視窗的方法如下:
driver.switch_to.window("視窗名")
或者你也可以在”switch_to_window()”中使用”視窗控制程式碼”來開啟它, 知道了這些,你就可以迭代所有已經開啟的視窗了:
for handle in driver.window_handles: driver.switch_to_window(handle)
八、訪問瀏覽器歷史記錄
-
在瀏覽歷史中前進和後退你可以使用:
driver.forward() driver.back()
九、cookies
-
獲取所有cookies
driver.get_cookies()
-
刪除某個cookie
driver.delete_cookie("CookieName")
-
刪除所有cookies
driver.delete_all_cookies()
十、頁面等待(Waits)
現在的大多數的Web應用程式是使用Ajax技術。當一個頁面被載入到瀏覽器時,該頁面內的元素可以在不同的時間點被載入。這使得定位元素變得困難,如果元素不再頁面之中,會丟擲ElementNotVisibleException異常。使用 waits, 我們可以解決這個問題。waits提供了一些操作之間的時間間隔,主要是定位元素或針對該元素的任何其他操作。
Selenium Webdriver 提供兩種型別的waits:隱式和顯式。顯式等待會讓WebDriver等待滿足一定的條件以後再進一步的執行。而隱式等待讓Webdriver等待一定的時間後再才是查詢某元素。
-
顯示等待
-
顯式等待是你在程式碼中定義等待一定條件發生後再進一步執行你的程式碼。
-
這裡有一些方便的方法讓你只等待需要的時間。WebDriverWait結合ExpectedCondition 是實現的一種方式。
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC driver = webdriver.Firefox() driver.get("http://somedomain/url_that_delays_loading") try: element = WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.ID, "myDynamicElement")) ) finally: driver.quit()
在丟擲TimeoutException異常之前將等待10秒。 WebDriverWait 預設情況下會每0.5秒呼叫一次ExpectedCondition直到結果成功返回。 ExpectedCondition成功的返回結果是一個布林型別的true或是不為null的返回值。
-
下面是一些內建的等待條件,你可以直接呼叫這些條件:
title_is title_contains presence_of_element_located visibility_of_element_located visibility_of presence_of_all_elements_located text_to_be_present_in_element text_to_be_present_in_element_value frame_to_be_available_and_switch_to_it invisibility_of_element_located element_to_be_clickable – it is Displayed and Enabled. staleness_of element_to_be_selected element_located_to_be_selected element_selection_state_to_be element_located_selection_state_to_be alert_is_present
-
-
隱氏等待
-
隱式等待比較簡單,就是簡單地設定一個等待時間,單位為秒。
-
如果不設定,預設等待時間為0秒。
from selenium import webdriver driver = webdriver.Firefox() driver.implicitly_wait(10) # seconds driver.get("http://somedomain/url_that_delays_loading") myDynamicElement = driver.find_element_by_id("myDynamicElement")
-
十一、執行JS
可以在載入完成的頁面上使用execute_script方法執行js。 比如呼叫javascript API滾動頁面到底部或頁面的任何位置
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
十二、傳檔案到檔案上傳控制元件
選擇 <input type="file"> 元素並且呼叫 send_keys() 方法傳入要上傳檔案的路徑,可以 是對於測試指令碼的相對路徑,也可以是絕對路徑。