一、Python+Selenium配置
- 前提條件: 已安裝好Python開發環境,版本3.5以上
- 安裝步驟:
1.1 打開cmd 輸入pip install selenium 點擊回車鍵,具體如下圖


1.2 把下載好的chromedriver.exe放到Python安裝目錄下,下載方法
二、啟動瀏覽器
2.1 普通啟動方式
#!/usr/bin/python3
# encoding:utf-8
from selenium import webdriver
#啟動Firefox瀏覽器
#browser = webdriver.Firefox()
#啟動IE瀏覽器
#browser = webdriver.Ie()
#啟動Chrome瀏覽器
#指定驅動方式啟動:webdriver.Chrome(executable_path="D://chromedriver.exe")
browser = webdriver.Chrome()
browser.get("http://www.baidu.com")
2.2 Headless啟動方式
說明:瀏覽器的無界面形態,無需打開瀏覽器即可運行,此種方式只chrome60+版本
#!/usr/bin/python3
# encoding:utf-8
from selenium import webdriver
chrome_hless = webdriver.ChromeOptions()
# 使用headless無界面瀏覽器模式
chrome_hless.add_argument('--headless')
chrome_hless.add_argument('--disable-gpu')
# 啟動瀏覽器,獲取網頁源代碼
browser = webdriver.Chrome(chrome_options=chrome_hless)
mainUrl = "https://www.baidu.com/"
browser.get(mainUrl)
print(browser.title)
browser.quit()
'''
運行之后結果打印百度標題:
百度一下,你就知道
'''
三、元素定位
| 元素 | 定位方法 |
|---|---|
| id | find_element_by_id() |
| name | find_element_by_name() |
| class | find_element_by_class_name() |
| link_text | find_element_by_link_text("全部文字匹配") |
| partial_link_text | find_element_by_partial_link_text("部分文字匹配") |
| tag | find_element_by_tag_name() |
| xpath | find_element_by_xpath() |
| css | find_element_by_css_selector() |
四、selenium三種等待方式
4.1 強制等待
固定等待XX秒時長
from selenium import webdriver
import time
time.sleep(3)
4.2 隱性等待
設置最長等待時長XX秒:
- 第一種情況:最長等待時長內瀏覽器一旦加載完成,直接進行下一步操作
- 第二種情況:超出設置最長等待時長,再進行下一步操作
# 瀏覽器加載完成,即進行下一步操作,如果10秒鍾還未加載完成,也進行下一步操作
driver.implicitly_wait(10)
4.3 顯性等待
WebDriverWait,配合該類的until()和until_not()方法,就能夠根據判斷條件而進行靈活地等待了。它主要的意思就是:程序每隔xx秒看一眼,如果條件成立了,則執行下一步,否則繼續等待,直到超過設置的最長時間,然后拋出TimeoutException
wait模塊的WebDriverWait類是顯性等待類,先看下它有哪些參數與方法:
selenium.webdriver.support.wait.WebDriverWait(類)
init
driver: 傳入WebDriver實例,即我們上例中的driver
timeout: 超時時間,等待的最長時間(同時要考慮隱性等待時間)
poll_frequency: 調用until或until_not中的方法的間隔時間,默認是0.5秒
ignored_exceptions: 忽略的異常,如果在調用until或until_not的過程中拋出這個元組中的異常,則不中斷代碼,繼續等待,如果拋出的是這個元組外的異常,則中斷代碼,拋出異常。默認只有NoSuchElementException。
until
method: 在等待期間,每隔一段時間(__init__中的poll_frequency)調用這個傳入的方法,直到返回值不是False
message: 如果超時,拋出TimeoutException,將message傳入異常
until_not
與until相反,until是當某元素出現或什么條件成立則繼續執行,
until_not是當某元素消失或什么條件不成立則繼續執行,參數也相同,不再贅述。
具如下
WebDriverWait(driver, 超時時長, 調用頻率, 忽略異常).until(可執行方法, 超時時返回的信息)
特別注意的是until或until_not中的可執行方法method參數,很多人傳入了WebElement對象,如下:
WebDriverWait(driver, 10).until(driver.find_element_by_id('kw')) # 錯誤
這是錯誤的用法,這里的參數一定要是可以調用的,即這個對象一定有 call() 方法,否則會拋出異常:
TypeError: 'xxx' object is not callable
在這里,你可以用selenium提供的 expected_conditions 模塊中的各種條件,也可以用WebElement的 is_displayed() 、is_enabled()、**is_selected() **方法,或者用自己封裝的方法都可以
WebDriverWait 常用方法表
| 對象 | 動作 |
|---|---|
| title_is | 判斷當前頁面的title是否完全匹配 |
| title_contains | 判斷當前頁面的title是否包含預期字符串 |
| presence_of_element_located | 判斷某個元素是否被加到了dom樹里,並不代表該元素一定可見 |
| visibility_of_element_located | 判斷某個元素是否可見.可見代表元素非隱藏,並且元素的寬和高都不等於0 |
| visibility_of | 跟上面的方法做一樣的事情,只是上面的方法要傳入locator,這個方法直接傳定位到的element就好了 |
| presence_of_all_elements_located | 判斷是否至少有1個元素存在於dom樹中。舉個例子,如果頁面上有n個元素的class都是'column-md-3',那么只要有1個元素存在,這個方法就返回True |
| text_to_be_present_in_element | 判斷某個元素中的text是否包含了預期的字符串 |
| text_to_be_present_in_element_value | 判斷某個元素中的value屬性是否包含了預期的字符串 |
| frame_to_be_available_and_switch_to_it | 判斷該frame是否可以switch進去,如果可以的話,返回True並且switch進去,否則返回False |
| invisibility_of_element_located | 判斷某個元素中是否不存在於dom樹或不可見 |
| element_to_be_clickable | 判斷某個元素中是否可見並且是enable的,這樣的話才叫clickable |
| staleness_of | 等某個元素從dom樹中移除,注意,這個方法也是返回True或False |
| element_to_be_selected | 判斷某個元素是否被選中了,一般用在下拉列表 |
| element_selection_state_to_be | 判斷某個元素的選中狀態是否符合預期 |
| element_located_selection_state_to_be | 跟上面的方法作用一樣,只是上面的方法傳入定位到的element,而這個方法傳入locator |
| alert_is_present | 判斷頁面上是否存在alert |
源碼舉例
#coding=utf-8
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
base_url = "http://www.baidu.com"
driver = webdriver.Chrome()
driver.implicitly_wait(5)
'''隱式等待和顯示等待都存在時,超時時間取二者中最大的'''
locator = (By.ID,'kw')
driver.get(base_url)
'''判斷title是否存在,返回布爾值'''
WebDriverWait(driver,10).until(EC.title_is(u"百度一下,你就知道"))
if WebDriverWait(driver,10).until(EC.title_is(u"百度一下,你就知道")) :
print("已找到標題百度一下,你就知道")
WebDriverWait(driver,10).until(EC.title_contains(u"百度一下"))
'''判斷某個元素是否被加到了dom樹里,並不代表該元素一定可見,如果定位到就返回WebElement'''
srk = WebDriverWait(driver,10).until(EC.presence_of_element_located((By.ID,'kw')))
#百度輸入框,輸入selenim
srk.send_keys("selenim")
'''判斷某個元素是否被添加到了dom里並且可見,可見代表元素可顯示且寬和高都大於0'''
WebDriverWait(driver,10).until(EC.visibility_of_element_located((By.ID,'su')))
'''判斷元素是否可見,如果可見就返回這個元素WebElement'''
WebDriverWait(driver,10).until(EC.visibility_of(driver.find_element(by=By.ID,value='kw')))
'''判斷是否至少有1個元素存在於dom樹中,如果定位到就返回WebElement列表'''
WebDriverWait(driver,10).until(EC.presence_of_all_elements_located((By.CSS_SELECTOR,'.mnav')))
'''判斷是否至少有一個元素在頁面中可見,如果定位到就返回WebElement列表'''
WebDriverWait(driver,10).until(EC.visibility_of_any_elements_located((By.CSS_SELECTOR,'.mnav')))
'''判斷指定的元素中是否包含了預期的字符串,返回布爾值'''
WebDriverWait(driver,10).until(EC.text_to_be_present_in_element((By.XPATH,"//*[@id='u1']/a[8]"),u'設置'))
'''判斷指定元素的屬性值中是否包含了預期的字符串,返回布爾值'''
WebDriverWait(driver,10).until(EC.text_to_be_present_in_element_value((By.CSS_SELECTOR,'#su'),u'百度一下'))
'''判斷該frame是否可以switch進去,如果可以的話,返回True並且switch進去,否則返回False'''
#WebDriverWait(driver,10).until(EC.frame_to_be_available_and_switch_to_it(locator))
#注意這里並沒有一個frame可以切換進去
'''判斷某個元素在是否存在於dom或不可見,如果可見返回False,不可見返回這個元素'''
WebDriverWait(driver,10).until(EC.invisibility_of_element_located((By.CSS_SELECTOR,'#swfEveryCookieWrap')))
#注意#swfEveryCookieWrap在此頁面中是一個隱藏的元素
'''判斷某個元素中是否可見並且是enable的,代表可點擊'''
WebDriverWait(driver,10).until(EC.element_to_be_clickable((By.XPATH,"//*[@id='u1']/a[8]"))).click()
driver.find_element_by_xpath("//*[@id='wrapper']/div[6]/a[1]").click()
'''等待某個元素從dom樹中移除'''
#WebDriverWait(driver,10).until(EC.element_to_be_clickable((By.XPATH,"//*[@id='wrapper']/div[6]/a[1]"))).click()
#WebDriverWait(driver,10).until(EC.staleness_of(driver.find_element(By.ID,'su')))
#這里沒有找到合適的例子
'''判斷某個元素是否被選中了,一般用在下拉列表'''
WebDriverWait(driver,10).until(EC.element_to_be_selected(driver.find_element(By.XPATH,"//*[@id='nr']/option[1]")))
'''判斷某個元素的選中狀態是否符合預期'''
WebDriverWait(driver,10).until(EC.element_selection_state_to_be(driver.find_element(By.XPATH,"//*[@id='nr']/option[1]"),True))
'''判斷某個元素的選中狀態是否符合預期'''
WebDriverWait(driver,10).until(EC.element_located_selection_state_to_be((By.XPATH,"//*[@id='nr']/option[1]"),True))
driver.find_element_by_xpath(".//*[@id='gxszButton']/a[1]").click()
'''判斷頁面上是否存在alert,如果有就切換到alert並返回alert的內容'''
instance = WebDriverWait(driver,10).until(EC.alert_is_present())
print(instance.text)
instance.accept()
driver.close()
五、瀏覽器操作
5.1 將瀏覽器最大化顯示
browser.maximize_window()
5.2 將瀏覽器最小化顯示
browser.minimize_window()
5.3 設置瀏覽器寬1366、高768顯示
browser.set_window_size(1366, 768)
5.4 瀏覽器前進、后退、退出、關閉
browser.forword()#前進
browser.back()#后退
browser.quit()#退出
browser.close()#關閉
六、.操作元素對象
| 對象- | 動作 |
|---|---|
| clear() | 清空 |
| send_keys() | 鍵盤操作 |
| click() | 點擊 |
| submit() | 提交 |
| text | 獲取對象文本 |
| get_attribute() | 獲取對象屬性值 |
源碼舉例
#coding=utf-8
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
base_url = "http://www.baidu.com"
driver = webdriver.Chrome()
driver.get(base_url)
driver.implicitly_wait(5)
#clear() 清空
driver.find_element(By.ID,'kw').clear()
#send_keys()輸入框鍵盤輸入select
driver.find_element(By.ID,'kw').send_keys("select")
#click()點擊對象
driver.find_element(By.ID,'su').click()
#submit()提交,注意類型type=‘submit’
driver.find_element(By.ID,'su').submit()
#text獲取元素文本值
button_name = driver.find_element_by_id('su').text
#get_attribute("type") 獲取屬性值
button_type = driver.find_element_by_id('su').get_attribute("type")
if button_type == "submit":
print("type為submit")
七、鍵盤事件
| 對象 | 動作 |
|---|---|
| send_keys(Keys.TAB) | TAB |
| send_keys(Keys.ENTER) | 回車 |
| send_keys(Keys.F12) | F12 |
| send_keys(Keys.CONTROL,'a') | ctrl+a |
源碼舉例
#coding=utf-8
from selenium import webdriver
import time
#鍵盤操作必須輸入包
from selenium.webdriver.common.keys import Keys
driver = webdriver.Chrome()
driver.get("http://www.baidu.com")
driver.implicitly_wait(5)
bdsrk = driver.find_element_by_id('kw')
bdsrk.send_keys('輸入')
#TAB
bdsrk.send_keys(Keys.TAB)
time.sleep(3)
#回車
bdsrk.send_keys(Keys.ENTER)
time.sleep(3)
#ctrl+a 全選輸入框內容
driver.find_element_by_id("kw").send_keys(Keys.CONTROL,'a')
time.sleep(3)
#F12
bdsrk.send_keys(Keys.F12)
driver.close()
八、.鼠標事件
| 對象 | 動作 |
|---|---|
| click | 單擊 |
| context_click() | 右擊 |
| double_click() | 雙擊 |
| drag_and_drop() | 拖動 |
| move_to_element() | 鼠標懸停 |
| click_and_hold | 按下鼠標左鍵在一個元素上 |
源碼舉例
#coding=utf-8
from selenium import webdriver
import time
#鼠標操作必須輸入包
from selenium.webdriver.common.action_chains import ActionChains
driver = webdriver.Chrome()
driver.get("http://www.baidu.com")
driver.implicitly_wait(5)
bdsrk = driver.find_element_by_id('kw')
#百度一下按鈕
bdan = driver.find_element_by_id('su')
#視頻鏈接
dt =driver.find_element_by_name("tj_trtieba")
time.sleep(3)
#單擊
bdsrk.click()
time.sleep(3)
#右擊
ActionChains(driver).context_click(bdsrk).perform()
time.sleep(3)
#雙擊
ActionChains(driver).double_click(bdan).perform()
time.sleep(3)
#鼠標拖放 從百度一下按鈕拖動到新聞鏈接位置
ActionChains(driver).drag_and_drop(bdan,dt)
time.sleep(3)
#鼠標懸停
ActionChains(driver).move_to_element(dt).perform()
time.sleep(3)
driver.close()
九、.多層框架/層級定位
定位元素過程中經常會遇到找不到元素的問題,出現該問題一般都是以下因素導致:
- 元素定位方法不對
- 頁面存在iframe或內嵌窗口
- 頁面超時
webdriver 提供了一個 switch_to_frame 方法,可以很輕松的來解決這個問題。
#先找到到 ifrome1(id = from1)
browser.switch_to_frame("from1")
十、Selenium速查表
| 異常 | 描述 |
|---|---|
| WebDriverException | 所有webdriver異常的基類,當有異常且不屬於下列異常時拋出 |
| InvalidSwitchToTargetException | 下面兩個異常的父類,當要switch的目標不存在時拋出 |
| NoSuchFrameException | 當你想要用switch_to.frame()切入某個不存在的frame時拋出 |
| NoSuchWindowException | 當你想要用switch_to.window()切入某個不存在的window時拋出 |
| NoSuchElementException | 元素不存在,一般由find_element與find_elements拋出 |
| NoSuchAttributeException | 一般你獲取不存在的元素屬性時拋出,要注意有些屬性在不同瀏覽器里是有不同的屬性名的 |
| StaleElementReferenceException | 指定的元素過時了,不在現在的DOM樹里了,可能是被刪除了或者是頁面或iframe刷新了 |
| UnexpectedAlertPresentException | 出現了意料之外的alert,阻礙了指令的執行時拋出 |
| NoAlertPresentException | 你想要獲取alert,但實際沒有alert出現時拋出 |
| InvalidElementStateException | 下面兩個異常的父類,當元素狀態不能進行想要的操作時拋出 |
| ElementNotVisibleException | 元素存在,但是不可見,不可以與之交互 |
| ElementNotSelectableException | 當你想要選擇一個不可被選擇的元素時拋出 |
| InvalidSelectorException | 一般當你xpath語法錯誤的時候拋出這個錯 |
| InvalidCookieDomainException | 當你想要在非當前url的域里添加cookie時拋出 |
| UnableToSetCookieException | 當driver無法添加一個cookie時拋出 |
| TimeoutException | 當一個指令在足夠的時間內沒有完成時拋出 |
| MoveTargetOutOfBoundsException | actions的move操作時拋出,將目標移動出了window之外 |
| UnexpectedTagNameException | 獲取到的元素標簽不符合要求時拋出,比如實例化Select,你傳入了非select標簽的元素時 |
| ImeNotAvailableException | 輸入法不支持的時候拋出,這里兩個異常不常見,ime引擎據說是僅用於linux下對中文/日文支持的時候 |
| ImeActivationFailedException | 激活輸入法失敗時拋出 |
| ErrorInResponseException | 不常見,server端出錯時可能會拋出 |
| RemoteDriverServerException | 不常見,好像是在某些情況下驅動啟動瀏覽器失敗的時候會報這個錯 |
