底层原理:
Selenium1.x
使用JavaScript注入技术与浏览器进行交互;
需要Selenium RC启动一个Server,将操作Web元素的API调用转化为一段段Javascript,在Selenium内核启动浏览器之后,将js注入(js可以获取调用DOM的任何元素);
缺点:速度不理想,稳定性依赖于翻译的js脚本正确性。
Selenium2.x
整合了selenium和webdriver,利用浏览器原生API,封装成一套Selenium WebDriver API;
使用浏览器原生API,直接操作浏览器中的元素,速度大大提升;
启动浏览器driver作为http server,脚本向server发送请求,获取sessionid,启动浏览器,携带sessionid操作浏览器,浏览器返回操作结果;
缺点:不同浏览器封装的webdriver不一样;
二次封装:
基于PO模式脚本开发方式,需要对selenium的各种操作进行二次封装,能够强化元素的查找和操作,同时提供统一的调用方式,使得脚本更加简洁;
一些封装例子:
def wait_elevisible(self,loc):
try:
start = time.time()
WebDriverWait(self.driver, 20, 0.5).until(EC.visibility_of_element_located(loc))
end = time.time()
log.info("{0}出现,等待时间{1}s".format(loc,round(end - start, 2)))
except:
log.error("未能等待元素出现。")
return self
def find_element(self,*loc):
return self.driver.find_element(*loc)
def click(self,loc): #点击操作
self.wait_elevisible(loc)
try:
log.info("点击:{0}".format(loc))
self.find_element(*loc).click()
except:
log.error("{0}点击失败".format(loc))
return self
def double_click(self,loc): #双击操作
self.wait_elevisible(loc)
try:
log.info("双击:{0}".format(loc))
ActionChains(self.driver).double_click(self.find_element(*loc)).perform()
except:
log.error("{0}双击失败".format(loc))
return self
def context_click(self,loc): #右键操作
self.wait_elevisible(loc)
try:
log.info("右击:{0}".format(loc))
ActionChains(self.driver).context_click(self.find_element(*loc))
except:
log.error("{0}右击失败".format(loc))
return self
def send_keys(self,loc,text): #输入操作
self.wait_elevisible(loc)
try:
log.info("在:{0}中输入:{1}".format(loc,text))
self.find_element(*loc).clear()
self.find_element(*loc).send_keys(text)
except:
log.error("输入操作失败")
return self