python webdriver点击指令_测开系列Selenium Webdriver Python(20)--Webdriver运行原理
Webdriver運行原理 轉帖請注明出處!謝謝
在開發Webdriver的自動化腳本過程中,Webdriver后臺在創建WebDriver實例的過程中,先確認瀏覽器的原生組件中是否存在可匹配的版本。然后在目標瀏覽器里啟動一整套Web Service(實際是瀏覽器廠商提供的driver, 比如IEDriver, ChromeDriver,它們都實現了WebDriver's wire protocol.),這套Web Service使用了Webdirver定義的通訊協議,名字叫做The WebDriver Wire Protocol。這套協議中定義了操作瀏覽器的執行動作包括打開、關閉、最大化、最小化、設置瀏覽器窗體大小、元素定位、元素點擊、上傳文件等。
WebDriver Wire協議是通用的。不管IE還是FirefoxDriver,ChromeDriver,甚至包括了AndroidDriver和iOS WebDriver,還有其他支持的三方瀏覽器,啟動綁定在特定端口上的的Web Service。如FirefoxDriver初始化成功之后,默認會從http://localhost:7055開始,而ChromeDriver則大概是http://localhost:46350之類的。接下來,調用WebDriver的任何API,都需要執行ComandExecutor發送指令,這條指令實際上是HTTP request發送給監聽端口上的Web Service。在HTTP request的body中,有符合WebDriver Wire協議規范的JSON格式的字符串來通知Webserver要求瀏覽器做什么。
可以這樣理解:客戶端腳本(java, python, ruby,c#)不能直接與瀏覽器通信,但可以用WebService作為通訊翻譯器,WebService把客戶端代碼翻譯成瀏覽器可以識別的代碼(如js)。客戶端(也就是測試腳本)創建1個session,在該session中通過http請求向WebService發送restful的請求,WebService翻譯成瀏覽器懂得腳本傳給瀏覽器,瀏覽器把執行的結果返回給WebService,WebService把返回的結果做了一些封裝(一般都是json格式),然后返回給client,根據返回值就能判斷對瀏覽器的操作是不是執行成功。
在登陸discuz代碼中:
driver=webdriver.Firefox()#創建webdriver的firefox實例 driver.get(url) #打開bbs項目首頁地址:r'http://192.168.0.110/discuz/forum.php'在執行driver.get(url) 代碼時,client也就是測試代碼向Web Service(remote server)發送了如下的請求:POST session/122b12e4-2c9s-5y74-90e1-9sdfs972ldss/url,post_data {"url":" http://192.168.0.110/discuz/forum.php "} 。
通過post的方式請求localhost:port/hub/session/session_id/url地址,請求瀏覽器完成跳轉url的操作。如果上述請求是可接受的,或者說Web Service是實現了這個接口,那么Web Service會跳轉到該post data包含的url,并返回如下的response:{"name":"get","sessionId":"122b12e4-2c9s-5y74-90e1-9sdfs972ldss","status":0,"value":""}。該response中包含信息:name:Web Service端的實現的方法的名稱,這里是get,表示跳轉到指定url;sessionId:當前session的id;status:請求執行的狀態碼,非0表示未正確執行,這里是0,表示一切ok不必擔心;value:請求的返回值,這里返回值為空,如果client調用title接口,則該值應該是當前頁面的title。
如果client發送的請求是find_element_by_id('ls_username') 函數定位頁面元素,則response的返回值是:{"name":"findElement","sessionId":"285b12e4-2b8a-4fe6-90e1-c35cba245956","status":0,"value":{"ELEMENT":"{2192893e-f260-44c4-bdf6-7aad3c919739}"}}。 name,sessionId,status跟前面例子一樣,區別是該請求的返回值是ELEMENT:{2192893e-f260-44c4-bdf6-7aad3c919739},表示定位到元素的id,通過該id,client可以發送如click之類的請求與server端進行交互。
總結下來核心就是Webdriver是按照server–client的架構設計,server端就是remote server,可以是任意的瀏覽器:腳本啟動瀏覽器后,該瀏覽器就是remote server,它的職責就是等待client發送請求并做出相應; client端簡單說來就是我們的測試代碼:測試代碼表示的是執行的動作行為,比如啟動瀏覽器,跳轉到指定的url等,這些操作本質都是以http請求的方式發送給被server端(也就是被測瀏覽器),server接受請求,并執行相應操作,并在response中返回執行狀態、返回值等信息。
Webdriver基本操作
WebDriver是一個接口,它展現了一個web瀏覽器,其自身主要實現了三個功能:控制瀏覽器本身 ,查找和選擇元素 ,調試程序比如異常處理。
實例:
from selenium import webdriver wb=webdriver.Firefox() print('driver attributes:') print(dir(wb))運行結果:
driver attributes: ['CONTEXT_CHROME', 'CONTEXT_CONTENT', 'NATIVE_EVENTS_ALLOWED', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_file_detector', '_is_remote', '_mobile', '_switch_to', '_unwrap_value', '_web_element_cls', '_wrap_value', 'add_cookie', 'application_cache', 'back', 'binary', 'capabilities', 'close', 'command_executor', 'context', 'create_web_element', 'current_url', 'current_window_handle', 'delete_all_cookies', 'delete_cookie', 'desired_capabilities', 'error_handler', 'execute', 'execute_async_script', 'execute_script', 'file_detector', 'file_detector_context', 'find_element', 'find_element_by_class_name', 'find_element_by_css_selector', 'find_element_by_id', 'find_element_by_link_text', 'find_element_by_name', 'find_element_by_partial_link_text', 'find_element_by_tag_name', 'find_element_by_xpath', 'find_elements', 'find_elements_by_class_name', 'find_elements_by_css_selector', 'find_elements_by_id', 'find_elements_by_link_text', 'find_elements_by_name', 'find_elements_by_partial_link_text', 'find_elements_by_tag_name', 'find_elements_by_xpath', 'firefox_profile', 'forward', 'get', 'get_cookie', 'get_cookies', 'get_log', 'get_screenshot_as_base64', 'get_screenshot_as_file', 'get_screenshot_as_png', 'get_window_position', 'get_window_rect', 'get_window_size', 'implicitly_wait', 'install_addon', 'log_types', 'maximize_window', 'mobile', 'name', 'orientation', 'page_source', 'profile', 'quit', 'refresh', 'save_screenshot', 'service', 'session_id', 'set_context', 'set_page_load_timeout', 'set_script_timeout', 'set_window_position', 'set_window_rect', 'set_window_size', 'start_client', 'start_session', 'stop_client', 'switch_to', 'switch_to_active_element', 'switch_to_alert', 'switch_to_default_content', 'switch_to_frame', 'switch_to_window', 'title', 'uninstall_addon', 'w3c', 'window_handles']技術解釋:wb=webdriver.Firefox(),wb指初始化了一個firefox的實例對象,就是類似一個真實瀏覽器。使用內建的dir函數來獲wb對象的所有屬性和方法。
實例:
from selenium import webdriver wb=webdriver.Firefox() wb.get('http://www.sohu.com') print('當前URL:'+wb.current_url) wb.get('http://www.youku.com') print('當前URL:'+wb.current_url)實例:
from selenium import webdriver wb=webdriver.Firefox() wb.get('http://www.sohu.com') print('當前Ttile:'+wb.title) wb.get('http://www.youku.com') print('當前Title:'+wb.title)實例:
from selenium import webdriver wb=webdriver.Firefox() wb.get('http://www.sohu.com') print(wb.page_source)實例:
from selenium import webdriver wb = webdriver.Firefox() wb.get("http://www.sohu.com/") print(wb.current_window_handle)實例:
from selenium import webdriver wb = webdriver.Firefox() wb.get("http://www.sohu.com/") newwindow = 'window.open("http://www.youku.com");' wb.execute_script(newwindow) handles = wb.window_handles print('打開所有tab頁的窗體句柄:') print(wb.window_handles)運行結果:
打開所有tab頁的窗體句柄:
['13', '148']技術解釋:整段代碼實現的是打開Firefox瀏覽器,開啟兩個tab頁,分別打開搜狐和優酷兩個網頁。代碼newwindow = 'window.open("http://www.youku.com");',newwindow字符串中保存的是一段JavaScript腳本,調用的是JS的內置對象window,Window 對象是 JavaScript 層級中的頂層對象,Window 對象代表一個瀏覽器窗口,open方法的作用是打開一個窗體,傳入參數是在窗體中打開鏈接。wb.execute_script作用是執行一段JS腳本。
實例:
from selenium import webdriver wb = webdriver.Firefox() wb.get("http://www.sohu.com/")技術解釋:學習過程中會發現一個問wb.get執行時間很長,driver.get(url)實現的功能是跳轉到指定的url,一直會等到頁面加載完畢后才會執行完,重點在頁面加載完成后,實際項目中如新聞類網站,視頻類網站,電商網站等,一般頁面前端代碼做了很多效果或者實現了很多功能,造成加載資源過多,導致頁面渲染時間過長。解決dirver.get不會因為加載時間引起的執行時間過長的問題,可以通過在driver中設置pageloadtimeout的方法設置加載頁面時間限制,以及異常處理解決,代碼如下:
import time from selenium import webdriver from selenium.common.exceptions import TimeoutException startTime = time.time() print("start time is: %0.3f"%startTime) driver = webdriver.Firefox() driver.set_page_load_timeout(3) # 設定頁面加載限制時間 try:driver.get('http://www.sohu.com/') except TimeoutException:print('time out after 2 seconds when loading page')driver.execute_script('window.stop()') #當頁面加載時間超過設定時間,通過執行Javascript來stop加載,即可執行后續動作 print('繼續執行')實例:
from selenium import webdriver wb=webdriver.Firefox() wb.get('http://www.sohu.com') wb.get('http://www.youku.com') wb.get('http://www.qq.com') wb.back() wb.forward()實例:
from selenium import webdriver wb=webdriver.Firefox() wb.get('http://www.sohu.com') wb.get('http://www.youku.com') wb.get('http://www.qq.com') wb.back()實例:
from selenium import webdriver wb=webdriver.Firefox() wb.get('http://www.sohu.com') wb.refresh()實例:
from selenium import webdriver wb = webdriver.Firefox() wb.get("http://www.sohu.com/") wb.close()實例:
from selenium import webdriver wb = webdriver.Firefox() wb.get("http://www.sohu.com/") wb.quit()實例:
from selenium import webdriver wb = webdriver.Firefox() wb.get("http://www.sohu.com/") wb.maximize_window()實例:
from selenium import webdriver wb=webdriver.Firefox() wb.set_window_size(1024,768) wb.get('http://www.sohu.com')實例:
from selenium import webdriver wb=webdriver.Firefox() wb.set_window_size(800,800) wb.get('http://www.sohu.com') print (wb.get_window_size())運行結果:
{'x': 3, 'height': 800, 'y': 3, 'width': 800}技術解釋:x,y是窗體在winow桌面上的左上角的坐標。
實例:
from selenium import webdriver wb=webdriver.Firefox() wb.set_window_size(800,800) wb.get('http://www.sohu.com') print (wb.get_window_position())運行結果:
{'width': 800, 'y': 3, 'height': 800, 'x': 3}實例:
from selenium import webdriver wb=webdriver.Firefox() wb.set_window_size(1024,768) wb.get('http://www.sohu.com') wb.get_screenshot_as_file(r'C:pngsohu.png')技術解釋:腳本可以通過設置瀏覽器窗口大小來測試符合當前分辨率下的測試場景。
實例:
from selenium import webdriver wb = webdriver.Firefox() wb.implicitly_wait(3) wb.get("http://www.sohu.com/") wb.find_element_by_link_text('搜狐首頁')技術解釋:當使用了implicitly_wait等待執行測試的時候,如果 WebDriver沒有在 DOM中找到元素,將繼續等待,超出設定時間后則拋出找不到元素的異常,換句話說,當查找元素或元素并沒有立即出現的時候,隱式等待將等待一段時間再查找 DOM,默認的時間是0,一旦設置了隱式等待,則它存在整個 WebDriver對象實例的聲明周期中,隱式的等到會讓一個正常響應的應用的測試變慢,它將會在尋找每個元素的時候都進行等待,這樣會增加整個測試執行的時間。
實例:
HTML代碼: <html lang="en"> <head><title>FrameSeleniumTest</title> </head> <body> <iframe src="http://www.sohu.com" id="frame" name="mycustomframe"></iframe> </body> </html>Webdriver代碼:
from selenium import webdriver wb = webdriver.Firefox() wb.switch_to.frame(0) # 用frame的index來定位,第一個是0 # wb.switch_to.frame("frame") # 用id來定位 # wb.switch_to.frame("mycustomframe") # 用name來定位實例:
from selenium import webdriver wb = webdriver.Firefox() wb.switch_to.frame(0) switch_to.default_content()實例:
from selenium import webdriver wb = webdriver.Firefox() wb.switch_to.frame(0) driver.switch_to.default_content()實例:
from selenium import webdriver wb = webdriver.Firefox() wb.get("http://www.sohu.com/") newwindow = 'window.open("http://www.youku.com");' wb.execute_script(newwindow) print(len(wb.window_handles)) second_window_handle=wb.window_handles[1] wb.switch_to_window(second_window_handle) #wb.switch_to.window(second_window_handle) wb.get('http://www.qq.com')技術解釋:Webdirver請求搜狐網之后,通過調用js腳本在Firefox新的窗口中打開優酷網,當前wb對象中保存了兩個窗口handle,為了操作js開的窗口,wb調用switch_to_window方法,把wb切換到新窗口中再請求騰訊網。在開發腳本的時候會看到switch_to_window有橫線, 針對selenium3 中的窗口定位會自動劃掉,不起作用現在換成driver.switch_to.window()
實例:Demo.HTML的HTML代碼:
<html> <head> <title>alert</title> <script language="javascript"> //JavaScript腳本標注alert("上聯:山石巖下古木枯");//在頁面上彈出上聯alert("下聯:白水泉邊少女妙");//在頁面上彈出下聯 </script> </head> </html> Webdriver代碼: from selenium import webdriver wb=webdriver.Firefox() wb.get(r'demo.html') alert=wb.switch_to_alert() alert.accept() alert.accept()技術解釋:alert,瀏覽器彈出框,一般是用來確認某些操作、輸入簡單的text或用戶名、密碼等,根據瀏覽器的不同,彈出框的樣式也不一樣,不過都是很簡單的一個小框。在firebug中是無法獲取到該框的元素的,也就是說alert是不屬于網頁DOM樹的。針對alert,selenium提供了相應的類來進行處理。selenium.webdriver.common.alert.Alert(driver)。alert的操作有:Alert(driver).accept() # 等同于點擊“確認”或“OK”;Alert(driver).dismiss() # 等同于點擊“取消”或“Cancel”;Alert(driver).authenticate(username,password) # 驗證,針對需要身份驗證的alert,目前還沒有找到特別合適的示例頁面;Alert(driver).send_keys(keysToSend) # 發送文本,對有提交需求的prompt框(上圖3);Alert(driver).text # 獲取alert文本內容,對有信息顯示的alert框.
實例:
from selenium import webdriver wb = webdriver.Firefox() wb.get("http://www.sohu.com") js="var q=document.documentElement.scrollTop=10000" wb.execute_script(js)技術解釋:該代碼實現打開守護網頁,拖動滾動條到底部,實現拖動滾動條到底部是利用js實現。
實例:
from selenium import webdriver wb = webdriver.Firefox() wb.get("http://www.sohu.com/") print(wb.get_cookies())運行結果:
[{'path': '/', 'name': 'ad_t_4', 'value': '2', 'httpOnly': False, 'secure': False, 'expiry': None, 'domain': 'www.sohu.com'}, {'path': '/', 'name': 'ad_t_3', 'value': '1', 'httpOnly': False, 'secure': False, 'expiry': None, 'domain': 'www.sohu.com'}, {'path': '/', 'name': 'ad_t_2', 'value': '2', 'httpOnly': False, 'secure': False, 'expiry': None, 'domain': 'www.sohu.com'}, {'path': '/', 'name': 'ad_t_5', 'value': '2', 'httpOnly': False, 'secure': False, 'expiry': None, 'domain': 'www.sohu.com'}, {'path': '/', 'name': 'ad_t_6', 'value': '1', 'httpOnly': False, 'secure': False, 'expiry': None, 'domain': 'www.sohu.com'}, {'path': '/', 'name': 'IPLOC', 'value': 'CN4201', 'httpOnly': False, 'secure': False, 'expiry': None, 'domain': '.sohu.com'}, {'path': '/', 'name': 'SUV', 'value': '1711111631162491', 'httpOnly': False, 'secure': False, 'expiry': None, 'domain': '.sohu.com'}, {'path': '/', 'name': 'beans_dmp_done', 'value': '1', 'httpOnly': False, 'secure': False, 'expiry': None, 'domain': '.sohu.com'}, {'path': '/', 'name': 'beans_new_turn', 'value': '%7B%22sohu-index%22%3A55%7D', 'httpOnly': False, 'secure': False, 'expiry': None, 'domain': 'www.sohu.com'}]實例:
from selenium import webdriver wb = webdriver.Firefox() wb.get("http://www.sohu.com") wb.add_cookie({'name':'key-aaaaaaa', 'value':'value-bbbb'}) print("1、遍歷所有cookie:" ) #遍歷cookies 中的name 和value 信息打印,當然還有上面添加的信息 for cookie in wb.get_cookies():print( "%s:%s" % (cookie['name'], cookie['value']) )實例:
from selenium import webdriver wb = webdriver.Firefox() wb.get("http://www.qq.com/") wb.delete_all_cookies() print('刪除后的cookie') print(wb.get_cookies())基于前面學習的Webdriver的屬性和方法,我們來繼續開發Discuz的測試腳本,利用前面學到的知識來增強測試腳本。
實例:
from selenium import webdriver #加載selenium庫 from selenium.webdriver.common.keys import Keys #加載selenium鍵盤定義庫forum_discuz_app_url='http://192.168.0.110/discuz/forum.php?mod=forumdisplay&fid=2' #Discuz! 程序發布板塊鏈接 forum_discuz_plugin_url='http://192.168.0.110/discuz/forum.php?mod=forumdisplay&fid=38' #Discuz!-插件板塊鏈接 forum_discuz_templet_url='http://192.168.0.110/discuz/forum.php?mod=forumdisplay&fid=39' #Discuz!-模板板塊鏈接 forum_discuz_appcenter_url='http://192.168.0.110/discuz/forum.php?mod=forumdisplay&fid=40' #Discuz!-應用中心板塊鏈接 forum_discuz_install_url='http://192.168.0.110/discuz/forum.php?mod=forumdisplay&fid=41'#Discuz!-安裝使用板塊鏈接 forum_discuz_master_url='http://192.168.0.110/discuz/forum.php?mod=forumdisplay&fid=42' #站長幫板塊鏈接 forum_discuz_bug_url='http://192.168.0.110/discuz/forum.php?mod=forumdisplay&fid=43' #Discuz!-BUG反饋板塊鏈接 def get_webdriver(url):# get_webdriver代碼實現在本書第一個webdriver腳本中 def login_discuz(driver,str_user,str_pwd):#登錄代碼的實現在本書第一個webdriver腳本技術解釋:以URL為結尾的變量保存了論壇子版塊的鏈接地址,這里用的變量保存,也可以用字典類型保存以上數據,論壇對應論壇鏈接。如:
frum_urls={'程序發布':'http://192.168.0.110/discuz/forum.php?mod=forumdisplay&fid=2','插件':'http://192.168.0.110/discuz/forum.php?mod=forumdisplay&fid=38','模板':'http://192.168.0.110/discuz/forum.php?mod=forumdisplay&fid=39','應用中心':'http://192.168.0.110/discuz/forum.php?mod=forumdisplay&fid=40','站長幫':'http://192.168.0.110/discuz/forum.php?mod=forumdisplay&fid=41','BUG反饋':'http://192.168.0.110/discuz/forum.php?mod=forumdisplay&fid=42'} def link_forum_check(driver):driver.get(forum_discuz_app_url)if driver.title=='Discuz! 程序發布 - Discuz! Board - Powered by Discuz!':print('論壇板塊Discuz! 程序發布頁面打開正確')driver.get(forum_discuz_plugin_url)if driver.title=='Discuz!-插件 - Discuz! Board - Powered by Discuz!':print('論壇板塊Discuz!-插件頁面打開正確')driver.get(forum_discuz_templet_url)if driver.title=='Discuz!-模板 - Discuz! Board - Powered by Discuz!':print('論壇板塊Discuz!-模板頁面打開正確')driver.get(forum_discuz_appcenter_url)if driver.title=='Discuz!-應用中心 - Discuz! Board - Powered by Discuz!':print('論壇板塊Discuz!-應用中心頁面打開正確')driver.get(forum_discuz_install_url)if driver.title=='Discuz!-安裝使用 - Discuz! Board - Powered by Discuz!':print('論壇板塊Discuz!-安裝使用頁面打開正確')driver.get(forum_discuz_master_url)if driver.title=='站長幫 - Discuz! Board - Powered by Discuz!':print('論壇板塊站長幫頁面打開正確')driver.get(forum_discuz_bug_url)if driver.title=='Discuz!-BUG反饋 - Discuz! Board - Powered by Discuz!':print('論壇板塊Discuz!-BUG反饋頁面打開正確')if __name__ == '__main__':#用變量存儲用戶名,密碼str_user="admin"str_pwd="admin"discuz_url=r'http://192.168.0.110/discuz/forum.php'wb=get_webdriver(discuz_url)login_discuz(wb,str_user,str_pwd)link_forum_check(wb)技術解釋:測試用例三要素:測試步驟,輸入數據,期望結果,測試腳本同樣需要測試步驟,測試數據,預期結果,只有預期結果才能驗證結果是否正確,上面腳本代碼是請求打開每一個論壇板塊的鏈接地址,然后驗證當前打開的頁面標題是否是論壇正確的標題,如果是正確的代表頁面打開正確。wb.title=='Discuz! 程序發布 - Discuz! Board - Powered by Discuz!',就是驗證代碼的實現,wb.title是獲得請求目標頁面后的標題,'Discuz! 程序發布 - Discuz! Board - Powered by Discuz!'是預期結果,通過if語句判斷在自動化測試中的結果是否正確。Webdriver把驗證discuz頁面中的論壇子板塊鏈接打開是否正確的功能封裝成link_forum_check(wb)函數。
實例:
import time from selenium import webdriver # 加載selenium庫 from selenium.webdriver.common.keys import Keys # 加載selenium鍵盤定義庫def get_webdriver(url):# get_webdriver代碼實現在本書第一個webdriver腳本中 def login_discuz(driver,str_user,str_pwd): # login_discuz的實現在本書第一個webdriver腳本def check_navigation_bar(driver,str_column):clink_ column = driver.find_element_by_link_text(str_column) # 點擊clink_ column.click()time.sleep(2)second_window_handle=driver.window_handles[1]driver.switch_to_window(second_window_handle)str_page_title=driver.titleif str_page_title=='云服務器 CVM - 騰訊云':print('導航欄目:'+str_column+'-頁面正常')if str_page_title=='基于 CentOS 搭建 Discuz 論壇 - 開發者實驗室 - 騰訊云':print('導航欄目:'+str_column+'-頁面正常')if str_page_title=='Discuz! 應用中心':print('導航欄目:'+str_column+'-頁面正常')if str_page_title=='Discuz! 官方站-PHP 開源論壇 - Powered by Discuz!':print('導航欄目:'+str_column+'-頁面正常')if str_page_title=='免費建站_Discuz! 專用主機服務_DZ動力':print('導航欄目:'+str_column+'-頁面正常')time.sleep(2)driver.close()mian_window_handle = driver.window_handles[0]driver.switch_to_window(mian_window_handle)技術解釋:Webdriver腳本中check_navigation_bar的功能是驗證導航欄欄目打開鏈接是否正確的函數,驗證的方法主要是通過打開新窗口之后通過瀏覽器標題來驗證。driver.window_handles獲得當前firefox打開所有頁面窗口的句柄,如果想遍歷打印當前瀏覽器的所有窗體的句柄,可以用下面的代碼,
for handle in driver.window_handles: driver.switch_to_window(handle)在check_navigation_bar每次打開一個欄目的鏈接,所以firefox會有兩個窗體,第二個打開的窗體就是打開的新鏈接,mian_window_handle = driver.window_handles[0]保存的就是新打開的導航欄欄目鏈接窗口的句柄。switch_to_window傳入mian_window_handle句柄值之后,driver指針執行了第二個窗口,這時候執行driver.close就是關閉欄目窗口,mian_window_handle = driver.window_handles[0],driver.switch_to_window(mian_window_handle)兩行代碼作用是driver重新把指針指向主窗口。
if __name__ == '__main__':# 用變量存儲用戶名,密碼str_user = "admin"str_pwd = "admin"discuz_url = r'http://192.168.0.110/discuz/forum.php'wb = get_webdriver(discuz_url)login_discuz(wb, str_user, str_pwd)time.sleep(2)check_navigation_bar(wb,'騰訊云主機')check_navigation_bar(wb, 'Discuz!實驗室')# check_navigation_bar(wb, '服務購買')check_navigation_bar(wb, '應用中心')check_navigation_bar(wb, '微社區')check_navigation_bar(wb, '在線體驗')技術解釋:上面實現的Webdriver腳本中涉及一個概念“句柄“。在Windows中,句柄是一個系統內部數據結構的引用。例如當用戶操作word文檔,其實打開的就是一個窗口,系統會給給這個窗口分配一個數值,系統會通知用戶:正在操作的窗口是188號窗口,就此用戶實現的應用程序通過這個數值,要求系統對188號窗口進行操作——移動窗口、改變窗口大小、把窗口最小化等等。實際上許多Windows API函數把句柄作為它的第一個參數,如GDI(圖形設備接口)句柄、菜單句柄、實例句柄、位圖句柄等,不僅僅局限于窗口函數。換句話說,句柄是一種內部代碼,通過它能引用受系統控制的特殊元素,如窗口、位圖、圖標、內存塊、光標、字體、菜單等。句柄專業的講是指使用的一個唯一的整數值,即一個四字節長的數值,來標志應用程序中的不同對象和同類對象中的不同的實例,諸如,一個窗口,按鈕,圖標,滾動條,輸出設備,控件或者文件等,它好比現實生活中的門牌號,只有獲得了門牌號,才能找到人的家,才能進門為所欲為。在上面的腳本中driver.switch_to_window(second_window_handle)后執行driver.title,才能得到當前窗體的標題,才能在之后關閉當前頁面窗口。這就是因為你獲得了句柄,才可以對當前窗口發號施令。
實例:
import time import os.path from selenium import webdriver # 加載selenium庫 from selenium.webdriver.common.keys import Keys # 加載selenium鍵盤定義庫page_correct_title = ['Discuz! 程序發布 - Discuz! Board - Powered by Discuz!','Discuz!-插件 - Discuz! Board - Powered by Discuz!','Discuz!-模板 - Discuz! Board - Powered by Discuz!','Discuz!-應用中心 - Discuz! Board - Powered by Discuz!','Discuz!-安裝使用 - Discuz! Board - Powered by Discuz!','站長幫 - Discuz! Board - Powered by Discuz!','Discuz!-BUG反饋 - Discuz! Board - Powered by Discuz!']forum_urls = ['http://192.168.0.110/discuz/forum.php?mod=forumdisplay&fid=2', #'程序發布':'http://192.168.0.110/discuz/forum.php?mod=forumdisplay&fid=38', #'插件':'http://192.168.0.110/discuz/forum.php?mod=forumdisplay&fid=39', #'模板':'http://192.168.0.110/discuz/forum.php?mod=forumdisplay&fid=40', #'應用中心':'http://192.168.0.110/discuz/forum.php?mod=forumdisplay&fid=41', # 'Discuz!-安裝使用':'http://192.168.0.110/discuz/forum.php?mod=forumdisplay&fid=41', #'站長幫':'http://192.168.0.110/discuz/forum.php?mod=forumdisplay&fid=42' # 'BUG反饋':] def get_webdriver(url):# get_webdriver代碼實現在本書第一個webdriver腳本中 def login_discuz(driver,str_user,str_pwd): #登錄代碼的實現在本書第一個webdriver腳本技術解釋:import time 主要是調用time.sleep方法,為了讓腳本執行成功,解決腳本執行完,頁面還沒有打開或者頁面元素還沒有出現的問題。import os.path是利用文件夾操作方法完成獲得保存截圖的文件夾。聲明page_correct_title ,forum_urls分別保存了論壇名稱和論壇地址,為了后面調用方便。
def link_forum_check(driver, forum_discuz_url, page_correct_title):driver.get(forum_discuz_url)if driver.title == page_correct_title:print(page_correct_title + ':論壇板塊頁面打開正確')return Trueelse:return Falsedef save_result_link_screenshot(driver,filename):dir_path=os.getcwd()png_filename=time.strftime('%Y-%m-%d %H-%M-%S',time.localtime(time.time()))+'-'+filename+'.png'screenshot_path=dir_path+'screen'+png_filenameprint(screenshot_path)if driver.save_screenshot(screenshot_path)==True:print(filename+'頁面截圖保存成功')else:print(filename + '頁面截圖保存失敗')技術解釋:link_forum_check是重新封裝了web基本操作第三部分的綜合實例A中的腳本link_forum_check函數,link_forum_check傳入三個參數driver, forum_discuz_url, page_correct_title,分別是webdriver實例,discuz子論壇鏈接地址,打開目標論壇板塊頁面的預期正確標題。save_result_link_screenshot(driver,filename)作用是保存頁面截圖,driver是webdirver實例,filename是頁面截圖的文件名稱。截圖文件的文件名稱規范是執行日期+時間+傳入的頁面截圖文件名稱.png。分析源碼driver.save_screeshot只能保存后綴為png文件,跟蹤save_screeshot函數調get_screenshot_as_file,內部源碼實現有這一段:
if not filename.lower().endswith('.png'):warnings.warn("name used for saved screenshot does not match file ""type. It should end with a `.png` extension", UserWarning)改段代碼lower是把文件名都變成小寫,if語句判斷文件后綴不是png的時候,提示文件后綴必須是png。
if __name__ == '__main__':# 用變量存儲用戶名,密碼str_user = "admin"str_pwd = "admin"discuz_url = r'http://192.168.0.110/discuz/forum.php'wb = get_webdriver(discuz_url)login_discuz(wb, str_user, str_pwd)for i in range(0, 7):if link_forum_check(wb, forum_urls[i], page_correct_title[i]):save_result_link_screenshot(wb,page_correct_title[i])技術解釋:入口函數分別調用獲得打開論壇主頁的webdriver的firefox實例,然后執行登錄,驗證論壇板塊打開鏈接是否正常。for i in range(0, 7)是遍歷論壇板塊,range中7可以改由len(forum_urls)來獲得論壇子版塊鏈接數會更高效,下次修改代碼只要修改forum_urls列表中的數據即可。
總結
以上是生活随笔為你收集整理的python webdriver点击指令_测开系列Selenium Webdriver Python(20)--Webdriver运行原理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: httpwebrequest超时时间ti
- 下一篇: tms570 can 接收大量数据_CA