1.selenium基本使用
1.selenium安裝及基本操作
selenium是一個自動化測試工具,它支持各種瀏覽器,包括Chrome,Safari,Firefox等主流界面瀏覽器驅動,也包括Phantomjs的無界面瀏覽器。
通過selenium+phantomjs可以直接渲染js
首先,需要下載不同瀏覽器的驅動,直接百度搜索就可以,例如搜過Chrome瀏覽器驅動,下載到本地
然后,將下載好的驅動放入到安裝python的根目錄下,例如C:/pyhton3/usr/bin,就是要把驅動和python.exe放在同一個文件夾。(虛擬環境也是一樣,放入對應的虛擬環境下的python的根目錄)
最后,通過pip安裝selenium模塊。
# coding = utf-8 import time from selenium import webdriver # 導入模塊 driver = webdriver.Chrome() # 1.聲明瀏覽器對象 driver.get('https://www.baidu.com') # 2. 訪問地址 # dirver.get('https://www.weibo.com') try: driver.save_screenshot('test.jpg') # 3.操作。截圖 finally: time.sleep(3) driver.close() # 4.關閉瀏覽器
這里模擬一個瀏覽器,訪問百度,並將瀏覽器打開后的頁面進行截圖。
2.元素選取
要用代碼操作瀏覽器,訪問網頁,做一些操作必須要通過定位,獲得要操作元素的位置,例如,要在百度輸入框搜索python關鍵詞,要經過如下操作:
首先,通過代碼定位到輸入框所在位置;
然后,通過代碼在輸入框中輸入關鍵字
最后,通過代碼實現點擊搜索。
import time from selenium import webdriver # 導入模塊 driver = webdriver.Chrome() # 1.聲明瀏覽器對象 driver.get('https://www.baidu.com') # 2. 訪問地址 try: # 通過審查元素,發現百度輸入框的id為kw, # 通過find_element_by_id("kw")定位到該輸入框 # 通過send_keys("Python") 實現在輸入框中輸入關鍵字 driver.find_element_by_id('kw').send_keys('python') # 輸入數據 # 同樣的,通過find_element_by_id定位“百度一下”按鈕 # 通過click()實現點擊 driver.find_element_by_id('su').click() finally: time.sleep(30) driver.close()
當然,還有很多其他方式來定位:
# 通過文本,定位貼吧的位置,並點擊 driver.find_element_by_link_text('貼吧').click() # 通過文本鏈接點擊進入 # 通過xpath路徑定位元素 driver.find_element_by_xpath('//*[@id="1"]/h3/a[1]').click() # 通過元素的name來定位,當然,后可以by_class_name() driver.find_element_by_name('loginname').send_keys('13212702940')
還有一些常用操作
print(driver.page_source) # 獲取網頁經過js渲染的源代碼,相當於審查元素 # driver.find_elements_by_id() # 獲取多個元素 # driver.find_element_by_css_selector
3.頁面交互
1.窗口切換
使用selenium操作瀏覽器的時候肯定會有很多窗口,selenium默認不切換窗口,所以需要有方法實現窗口的切換。
切換窗口有如下方法:
通過driver.window_handlers獲取每個窗口的操作對象,然后for循環,實現切換窗口的目的。
for handler in driver.window_handlers: driver.switch_to_window(handler)
2.cookies處理
在selenium中,cookies的用法一般是通過模擬登陸之后,獲取到cookies值,再通過requests等庫實現請求,
增加效率。
cookie = {} for item in driver.get_cookies(): cookie[item.get('name')] = item.get('value')
3.元素拖動
在selenium中,除了簡單的點擊動作外,還有一些稍微復雜的動作,例如元素的拖動。
在實現元素拖動中時,需要另一個模塊。ActionChains模塊滿足對鼠標操作的要求。
ActionChains的執行原理就是當調用ActionChains方法時,不會立即執行,而是將所有操作暫時放在一個隊列中,
當調用perform()方法時,隊列會按照放入的先后順序,依次執行。
例如驗證碼的滑動,其實就是將一個元素拖動到某一個位置,然后松開,因此,元素的拖動經過下面幾個步驟:
將鼠標移上去,點擊鼠標左鍵不放,拖拽到目的點,松開鼠標
ActionChains中提供的方法:
# 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) # 鼠標移動到距離當前位置(x, y) # move_to_element(to_element) # 移動到某個元素 # # # 將鼠標移動至距離某個元素多少距離的位置 # move_to_element_with_offset(to_element, xoffset, yoffset) # # release(on_element=None) # 在某個元素位置松開鼠標左鍵 # perform() # 執行鏈中的所有動作
來一個簡單拖拽例子,測試網址:http://www.treejs.cn/v3/demo/cn/exedit/drag.html
# 實例化一個瀏覽器 driver = webdriver.Chrome() try: # 打開頁面(可以自己先打開試一下) driver.get('http://www.treejs.cn/v3/demo/cn/exedit/drag.html') time.sleep(2) # 1.通過id定位要拖動的元素元素(相當於鼠標移上去) element = driver.find_element_by_id('treeDemo_2_span') # 2.通過id定位要拖到的位置 target = driver.find_element_by_id('treeDemo_3_span') # 拖動元素到目標位置 ActionChains(driver).drag_and_drop(element, target).perform() time.sleep(15) finally: driver.quit()
4.彈窗處理
很多網頁里面可能會出現彈窗,需要對彈窗進行一定的處理(就是js里的alert())。
使用:
driver.switch_to_alert() # 切換到彈窗
time.sleep(3)
driver.accept() #接收彈窗
對彈窗進行處理。
4.頁面等待
現在的大多數web應用,越來越多采用了Ajax技術,以及程序不能確定某個元素何時完全加載出來,
這會讓元素定位困難,會提高ElementNotVisibleException的概率,因此出現了等待。
就是等待頁面中,某個元素出現,就執行某些代碼。selenium提供兩種等待方式。
1.顯式等待
顯式等待是指定某個條件,然后設置最長等待時間,如果在這個時間里面還沒有找到元素,那么就拋出異常。
顯式等待主要使用了WebDriverWait類和excepted_conditions模塊。
WebDriverWait是顯式等待類,主要方法有:
__init__中:
- driver:傳入的WebDriver實例
- timeout:超時時間,等待的最長時間(同時要考慮隱性等待時間)
- poll_frequency:調用until中的方法的間隔時間,默認0.5s
- ignored_exception:忽略的異常,如果在調用until過程中,拋出這個異常,則不中斷代碼,繼續執行
如果拋出的是這個元組外的異常,則代碼中觀,拋出異常,默認只有NoSuchElementException
until中:
- method:在等待期間,每隔一段時間,調用這個傳入的方法,直到返回值不是False
- message:如果超時,拋出TimeOutException,將message傳入異常。
expected_conditions是selenium的一個模塊,其中包含一系列等待的條件:
""" title_is title_contains #這兩個條件類驗證title,驗證傳入的參數title是否等於或包含於driver.title presence_of_element_located presence_of_all_elements_located 這兩個人條件驗證元素是否出現,傳入的參數都是元組類型的locator,如(By.ID, 'kw') 顧名思義,一個只要一個符合條件的元素加載出來就通過;另一個必須所有符合條件的元素都加載出來才行 visibility_of_element_located invisibility_of_element_located visibility_of 這三個條件驗證元素是否可見,前兩個傳入參數是元組類型的locator,第三個傳入WebElement 第一個和第三個其實質是一樣的 text_to_be_present_in_element text_to_be_present_in_element_value 這兩個人條件判斷某段文本是否出現在某元素中,一個判斷元素的text,一個判斷元素的value frame_to_be_available_and_switch_to_it # 有些頁面有frame標簽,該標簽出現后才能定位,例如QQ空間 這個條件判斷frame是否可切入,可傳入locator元組或者直接傳入定位方式:id、name、index或WebElement alert_is_present 這個條件判斷是否有alert出現 element_to_be_clickable 這個條件判斷元素是否可點擊,傳入locator """
簡單例子:訪問百度首頁,等待“貼吧”那個地方出現,出現后就拿它的鏈接
from selenium import webdriver from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By driver = webdriver.Chrome() driver.get('https://baidu.com') locator = (By.LINK_TEXT, '貼吧') try: # 等待,直到locator出現為止,driver在20s內,每0.5s檢查一次該元素是否出現 # 出現,執行后面內容;沒出現,繼續等待(20s內,超過就拋異常) WebDriverWait(driver, 20, 0.5).until(EC.presence_of_element_located(locator)) # 出現后直接獲取貼吧的鏈接 print(driver.find_element_by_link_text('貼吧').get_attribute('href')) finally: driver.close()
2.隱式等待
隱性等待implicitly_wait(xx),隱形等待是設置了一個最長等待時間,
如果在規定時間內網頁加載完成,則執行下一步,
否則一直等到時間截止,然后執行下一步。
弊端就是程序會一直等待整個頁面加載完成,就算你需要的元素加載出來了還是需要等待。
from selenium import webdriver driver = webdriver.Chrome() driver.implicitly_wait(30) driver.get('https://www.baidu.com')
2.Phantomjs的使用
PhantomJS是一個無界面的,可腳本編程的WebKit瀏覽器引擎。
它原生支持多種web 標准:DOM 操作,CSS選擇器,JSON,Canvas 以及SVG。
phantomjs常用配置:
# 引入配置對象DesiredCapabilities from selenium.webdriver.common.desired_capabilities import DesiredCapabilities dcap = dict(DesiredCapabilities.PHANTOMJS) #從USER_AGENTS列表中隨機選一個瀏覽器頭,偽裝瀏覽器 dcap["phantomjs.page.settings.userAgent"] = (random.choice(USER_AGENTS)) # 不載入圖片,爬頁面速度會快很多 dcap["phantomjs.page.settings.loadImages"] = False # 設置代理 service_args = ['--proxy=127.0.0.1:9999','--proxy-type=socks5'] #打開帶配置信息的phantomJS瀏覽器 driver = webdriver.PhantomJS(phantomjs_driver_path, desired_capabilities=dcap, service_args=service_args)
# 如果你的phantomjs配置了環境變量,就不需要填寫路徑(phantomjs_driver_path),否則需要添加你的phantomjs所在的路徑
3.模擬登陸
利用selenium登錄新浪微博,首先訪問新浪頁面,等待輸入賬號和密碼的輸入框出現,然后依次利用selenium輸入賬號和密碼,最后點擊登錄,並獲取登陸后的源碼。
# coding = utf-8 """ 用selenium登錄新浪微博 """ import time from selenium import webdriver from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By # 1,實例化瀏覽器驅動 driver = webdriver.Chrome() url = 'https://weibo.com/' # 2,給定訪問目標 driver.get(url) # 定位賬號密碼輸入框並登錄 username = '184419810@qq.com' password = '*********' try: # 創建等待事件 waiter = WebDriverWait(driver, 20, 0.1) event = (By.XPATH, '//*[@id="pl_login_form"]') # # 等待登錄框的出現 waiter.until(EC.presence_of_element_located(event)) # 賬號輸入 driver.find_element_by_xpath('//*[@id="loginname"]').send_keys(username) time.sleep(1) # 密碼輸入 driver.find_element_by_xpath('//*[@id="pl_login_form"]/div/div[3]/div[2]/div/input').send_keys(password) time.sleep(1) # 點擊登錄 driver.find_element_by_xpath('//*[@id="pl_login_form"]/div/div[3]/div[6]/a').click() # 獲取登錄后的源碼 print(driver.page_source) except Exception as e: print(e) finally: time.sleep(10) driver.close()
