Python---13.web自动化工具selenium
selenium作用:
-
自动化测试:通过它,我们可以写出⾃动化程序,模拟浏览器⾥操作web界⾯。 ⽐如点击界⾯按钮,在⽂本框中输⼊⽂字等操作。
-
获取信息:⽽且还能从web界⾯获取信息。 ⽐如招聘⽹站职位信息,财经⽹站股票价格信息 等等,然后⽤程序进⾏分析处理。
selenium环境:测试直接运⾏在浏览器中,就好像⼀个真正的⽤⼾在操作⼀样,⽀持⼤部分主流的浏览器,包括IE(7,8,9,10,11),Firefox,Safari,Chrome,Opera等。
selenium基本使用:
自动化程序selenium库→浏览器驱动,浏览器厂商提供→浏览器 Chrome,Firefox
-
selenium安装:建议安装selenium4.0.0版本,因为我们在给图片定位的时候(0,0)坐标点是选在图片的左上角位置的,4.0.0版本后的版本是以图片中心定位。浏览器驱动可以自行到网上搜索对应的安装。
-
元素选取:
-
⽼版本selenium:
在⼀个⻚⾯中有很多不同的策略可以定位⼀个元素。我们可以选择最合适的⽅法去查找元素。Selenium提供了下列的⽅法。
单个元素查找⽅法
作⽤
find_element_by_xpath()
通过Xpath查找
find_element_by_class_name()
通过class属性查找
find_element_by_id()
通过id属性查找
find_element_by_name()
通过name属性进⾏查找
-
新版本的⽤法:By对象查找,除了以上的多种查找⽅式,还有两种私有⽅法集成了上⾯的所有的查找⽅法,让我们更⽅便的使⽤。
find_element(By.XPATH, ‘//button/span’)
通过Xpath查找⼀个
find_elements(By.XPATH, ‘//button/span’)
通过Xpath查找多个
其中的第⼀个参数可以选择使⽤查找的⽅法,By.xxx使⽤xxx⽅式解析,解析⽅法如下:
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"# from selenium import webdriver # from selenium.webdriver.common.by import By # wb = webdriver.Edge() # wb.get('https://movie.douban.com/top250') # wb.find_element(By.XPATH, '//span[@class="title"]') -
文本输⼊和提交:
# from selenium import webdriver # from selenium.webdriver.common.by import By # # # wb = webdriver.Edge() # wb.get("https://www.baidu.com") # wb.find_element(By.ID,"chat-textarea").send_keys("周杰伦") # wb.find_element(By.ID,"chat-submit-button").click()
-
-
动作切换:
-
窗⼝切换:⽤selenium操作浏览器如果需要在打开新的⻚⾯,这个时候会有问题,因为我们⽤selenium操作的是第⼀个打开的窗⼝,所以新打开的⻚⾯我们是⽆法去操作的,所以我们要⽤到切换窗⼝:即handle切换的⽅法。
⽅法
作⽤
js = 'window.open("https://www.baidu.com");'chrome.execute_script(js)
打开新标签
window_handles
获取所有⻚⾯窗⼝的句柄
current_window_handle
获取当前⻚⾯窗⼝的句柄
switch_to.window(window_name)
定位⻚⾯转到指定的window_name
⻚⾯
# from selenium import webdriver # from selenium.webdriver.common.by import By # # # wb = webdriver.Edge() # wb.execute_script('window.open("https://www.baidu.com")') # wb.execute_script('window.open("https://www.4399.com")') # wb.execute_script('window.open("https://www.vip.com")') # wb.execute_script('window.open("https://www.bing.com")') # # wins = wb.window_handles # print(wb.current_window_handle) # print(wins) # wb.switch_to.window(wins[1]) # print(wb.title)注意:Window_handles的顺序并不是浏览器上标签的顺序,尽量避免多标签操作。
-
⻚⾯切换:在实际的爬⾍中,明明定位的路径没问题,这个时候我们可以考虑⼀下是否是该⻚⾯存在frame的问题导有时候我们会遇到找不到元素的问题致的定位不到元素。
⽅法
作⽤
switch_to.frame(frame_reference)
切到指定frame,可⽤id或name(str)、index(int)、元素(WebElement)定位
switch_to.parent_frame()
切到⽗级frame,如果已是主⽂档,则⽆效果, 相当于后退回去
switch_to_default_content()
切换到主⻚⾯,DOM树最开始的frame
# # coding=utf-8 # import time # # from selenium import webdriver # from selenium.webdriver.common.by import By # # wb = webdriver.Edge() # wb.maximize_window() # # wb.get('https://study.163.com/') # # time.sleep(1) # wb.find_element(by=By.XPATH, value='//span[@class="ux-btn th-bk-main ux-btn- ux-btn- ux-modal-btn um-modal-btn_ok th-bk-main"]').click() # wb.find_element(by=By.ID, value='j-nav-login').click() # time.sleep(1) # # 切换iframe标签的操作 # fr = wb.find_element(by=By.XPATH, value='//iframe[@frameborder="0"]') # wb.switch_to.frame(fr) # # wb.find_element(by=By.ID, value='phoneipt').send_keys('18300000000') # wb.find_element(by=By.XPATH, value='//input[@placeholder="请输入密码"]').send_keys('qwe12345678') # # wb.switch_to.default_content() # 切换到主页面 # wb.find_element(by=By.XPATH,value='//a[@class="ux-modal_close"]').click() -
⻚⾯弹窗:有的时候还会遇到弹窗的问题, 主要有两种⼀种是浏览器弹窗(alert/prompt),⼀种是⾃定义弹窗 ⾃定义弹窗,就是⼀个⾃定义的div层,是隐藏⻚⾯中的,当触发了这个弹窗后,他就显⽰出来,这种⽅式我们通过正 常的定位⽅式是可以定位到的。alert弹窗,就要⽤下⾯的⽅法处理:
⽅法
作⽤
switch_to
定位到alert弹窗,返回⼀个弹窗的对象
dismiss()
对弹窗对象的取消操作(相当于点击弹窗上的取消按钮)
accept()
对弹窗对象的确定操作(相当于点击弹窗上的确定按钮)
send_keys(key)
对弹窗对象内的输⼊框输⼊数据(针对于prompt弹窗)
text
获取弹窗内的⽂本
-
-
等待:
在selenium操作浏览器的过程中,每⼀次请求url,selenium都会等待⻚⾯加载完成以后,才会将操作权限在交给我们的程序。但是,由于ajax和各种JS代码的异步加载问题,当⼀个⻚⾯被加载到浏览器时,该⻚⾯内的元素可以在不同的时间点被加载,这就使得元素的定位变得⼗分困难,当元素不再⻚⾯中时,使⽤selenium去查找的时候会抛出ElementNotVisibleException异常。
为了解决这个问题,selenium提供了两种等待⻚⾯加载的⽅式,显⽰等待和隐式等待,让我们可以等待元素加载完成后在进⾏操作。
-
显式等待:
显式等待指定某个条件,然后设置最⻓等待时间,程序每隔XX时间看⼀眼,如果条件成⽴,则执⾏下⼀步,否则继续等待,直到超过设置的最⻓时间,然后抛出超时异常(TimeoutException)。显⽰等待主要使⽤了WebDriverWait类与expected_conditions模块。
⼀般写法:WebDriverWait(driver, timeout, poll_frequency,igonred_exceptions).until(method, message)
driver:传⼊WebDriver实例
timeout:超时时间,等待的最⻓时间(同时要考虑隐性等待时间)
poll_frequency:调⽤until中的⽅法的间隔时间,默认是0.5秒
ignored_exceptions:忽略的异常,如果在调⽤until的过程中抛出这个元组中的异常,则不中断代码,继续等待
method:可执⾏⽅法
message:超时时返回的信息# 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 # # wb = webdriver.Edge() # wb.maximize_window() # # wb.get('https://study.163.com/') # # wb.find_element(by=By.XPATH, value='//span[@class="ux-btn th-bk-main ux-btn- ux-btn- ux-modal-btn um-modal-btn_ok th-bk-main"]').click() # wb.find_element(by=By.ID, value='j-nav-login').click() # # data = (By.XPATH, '//iframe[@frameborder="0"]') # WebDriverWait(driver=wb, timeout=5, poll_frequency=0.3).until(EC.presence_of_element_located(data), message='Not Found') # # # 切换iframe标签的操作 # fr = wb.find_element(by=By.XPATH, value='//iframe[@frameborder="0"]') # wb.switch_to.frame(fr) # # wb.find_element(by=By.ID, value='phoneipt').send_keys('18300000000') # wb.find_element(by=By.XPATH, value='//input[@placeholder="请输入密码"]').send_keys('qwe12345678') # # wb.switch_to.default_content() # 切换到主页面 # wb.find_element(by=By.XPATH,value='//a[@class="ux-modal_close"]').click() -
隐性等待:隐性等待implicitly_wait(xx) :设置了⼀个最⻓等待时间,如果在规定时间内⽹⻚加载完成,则执⾏下⼀步,否则⼀直等到时间截⽌,然后执⾏下⼀步。
弊端是程序会⼀直等待整个⻚⾯加载完成,就算你需要的元素加载出来了还是需要等待,也就是⼀般情况下你看到浏览器标签栏那个⼩圈不再转,才会执⾏下⼀步,隐性等待对整个driver的周期都起作⽤,所以只要设置⼀次即可。# from selenium import webdriver # driver = webdriver.Chrome() # driver.implicitly_wait(10) #隐式等待,最长10s # driver.get('https://www.baidu.com')隐性等待和显性等待可以同时⽤,但要注意:等待的最⻓时间取两者之中的⼤者,默认等待时间为0。
-
强制等待:强制等待就是不论如何,在此处都需要阻塞等待⼀段时间,及time.sleep()
-
- 动作链:在selenium当中除了简单的点击动作外,还有⼀些稍微复杂的动作,就需要⽤到ActionChains(动作链)这个⼦模块来满⾜我们的需求。
ActionChains可以完成复杂⼀点的⻚⾯交互⾏为,例如元素的拖拽,⿏标移动,悬停⾏为,内容菜单交互。
它的执⾏原理就是当调⽤ActionChains⽅法的时候不会⽴即执⾏,⽽是将所有的操作暂时储存在⼀个队列中,当调⽤perform()⽅法的时候,会按照队列中放⼊的先后顺序执⾏前⾯的操作。ActionChains包:from selenium.webdriver.common.action_chains import ActionChainsActionChains提供的⽅法作⽤click(on_element=None)⿏标左键单击传⼊的元素double_click(on_element=None)双击⿏标左键context_click(on_element=None)点击⿏标右键click_and_hold(on_element=None)点击⿏标左键,按住不放release(on_element=None)在某个元素位置松开⿏标左键drag_and_drop(source, target)拖拽到某个元素然后松开drag_and_drop_by_offset(source, xoffset, yoffset)拖拽到某个坐标然后松开move_to_element(to_element)⿏标移动到某个元素move_by_offset(xoffset, yoffset)移动⿏标到指定的x,y位置move_to_element_with_offset(to_element, xoffset, yoffset)将⿏标移动到距某个元素多少距离的位置perform()执⾏链中的所有动作from selenium.webdriver import ActionChains from selenium.webdriver.common.by import By from selenium import webdriver wb = webdriver.Edge() wb.maximize_window() url = 'https://www.runoob.com/try/try.php?filename=jqueryui-api-droppable' wb.get(url) # 需要选择iframe对象 frame = wb.find_element(by = By.ID , value = "iframeResult") wb.switch_to.frame(frame) # 定位到小方块 duixiang1 = wb.find_element(by = By.ID , value = "draggable") # 实例化动作链对象 action1 = ActionChains(wb) # 把鼠标放到这个元素上,按鼠标左键,不松开 action1.click_and_hold(duixiang1) # 往右移动一定的距离 action1.move_by_offset(280 , 0) # 松开鼠标左键 action1.release() # 执行动作链的操作 action1.perform()
更多推荐
所有评论(0)