为了写自动化脚本,但是selenium的查找元素名字太长了,以至于效率上不去
比如说,能不能将browser.find_element_by_id()函数直接简化写成byid()这样的函数呢,答案是可以,自己用了两种方法来实现,由于对python水平认知有限,如果写的不到位还请多多指点.
第一种方法是自己写一个类库Bsl和一个方法chrome.方法用来打开浏览器(chrome和ie)并返回浏览器对象.把浏览器对象传入我们的类库,就可以直接改写我们想要的功能函数,但是有个缺点就是需要每次操作将对象指针初始化,因为操作一次,对象的指针就移动到定位的元素了,不过好处就是不用在重新查找元素,当前元素直接点击就可以.直接上代码
#encoding=utf-8”’## @description 封装一个selenium类# @author benty 2021-04-13 17:51:06# @param# @return#”’from selenium import webdriverfrom time import sleepimport osfrom selenium.webdriver.common.desired_capabilities import DesiredCapabilities# from selenium.webdriver.support.wait import WebDriverWaitfrom selenium.webdriver.support import expected_conditions as ECfrom selenium.webdriver.support.ui import WebDriverWaitimport timefrom selenium.webdriver.common.keys import Keys# DesiredCapabilities.INTERNETEXPLORER[‘ignoreProtectedModeSettings’] = Truedef chrome(url=””,type=”chrome”,t=15):”’初始化浏览器并打开”’if type==”chrome”:options = webdriver.ChromeOptions()options.add_argument(‘–log-level=3’)options.add_experimental_option(‘excludeSwitches’,[‘enable-logging’])options.add_argument(‘disable-infobars’)# options.add_argument(‘headless’)#静默模式b=webdriver.Chrome(options=options,service_log_path=os.devnull,desired_capabilities = None)else:#不是chrome就是IEpath = r’D:\work\python\自动化\清华控股\tools\IEDriverServermabt.exe’b = webdriver.Ie(executable_path=path)sleep(1)b.implicitly_wait(t)b.get(url)# WebDriverWait(self.b, 10).until(lambda x: self.b.find_element_by_link_text(‘hao123’))#显式等待# print(‘=========================================================’)b.maximize_window() # 放大页面return bclass Bsl():”’封装浏览器的查找元素功能”’def __init__(self,obj={}):”’初始化浏览器并打开”’self.b=objself.init=obj#测试学习#下面都是获取一个结果def byid2(self,elem):”’获取id,直接写名字不用加#”’pass# return self.b.find_element_by_id# return self#下面都是获取一个结果def byid(self,elem):”’获取id,直接写名字不用加#”’self.b=self.b.find_element_by_id(elem)return selfdef byclass(self,elem):”’必须获取class元素的第一个元素”’self.b=self.b.find_element_by_class_name(elem)return selfdef byname(self,elem):”’必须获取标签的第一个name属性元素”’self.b=self.b.find_element_by_name(elem)return selfdef byxpath(self,elem):”’必须根据xpath找到第一个元素”’self.b=self.b.find_element_by_xpath(elem)return selfdef bytagname(self,elem):”’必须获取一个html标签”’self.b=self.b.find_element_by_tag_name(elem)return selfdef bycss(self,css):”’必须根据css选择器找到一个元素”’self.b=self.b.find_element_by_css_selector(css)return self#下面都是获取多个结果返回列表def byclasses(self,elem):”’获取class元素并返回一个列表”’self.b=self.b.find_elements_by_class_name(elem)return selfdef bynames(self,elem):”’获取标签的name属性返回一个列表”’self.b=self.b.find_elements_by_name(elem)return selfdef byxpaths(self,elem):”’根据xpath获取一个列表”’self.b=self.b.find_elements_by_xpath(elem)return selfdef bytagnames(self,elem):”’获取html标签列表”’self.b=self.b.find_elements_by_tag_name(elem)return selfdef bycsss(self,css):”’根据css返回一个元素列表”’self.b=self.b.find_elements_by_css_selector(css)return self#封装其他功能def title99(self):self.b=self.b.titledef attr(self,attrk):”’封装get_attribute()”’tmp=self.b.get_attribute(attrk)self.b=self.initreturn tmpdef atext(self,txt):”’根据标签文本找元素”’self.b=self.b.find_element_by_link_text(txt)return self@propertydef text(self):”’返回属性并初始化对象”’tmp=self.b.textself.b=self.initreturn tmpdef toframe(self,name):”’切换到其他frame页面找内容”’self.b.switch_to.frame(name)return selfdef todefault(self):”’切换到默认frame,不需要返回”’self.b.switch_to.default_content()return selfdef runjs(self,str):”’执行js代码”’self.init.execute_script(str)# return selfdef wait(self,time=10):”’等待elem元素出现”’return WebDriverWait(self.b,time)def pagewait(self,keywords,textobj,waittime=15):”’判断关键词keywords是否在textobj,不在一直等,存在返回1,主要对ajax页面进行分析”’ppagestat=0timek=0while ppagestat==0:if keywords in textobj:ppagestat=1else:print(“else等待元素出现”)time.sleep(0.5)timek+=1if timek>waittime*2:#默认最大等待时间30s,超时跳出breakreturn ppagestat@propertydef out(self):”’返回操作对象指针,可调用find_element_XXX”’return self.b@propertydef outin(self):”’返回self对象自身,可重新链式调用类方法”’return self@propertydef ini(self):”’重置类对象指针,初始化浏览器对象”’self.b=self.initreturn self#结束浏览器进程def close(self):”’关闭浏览器”’self.b.quit()# self.b.file_detector_contextif __name__ == ‘__main__’:#在当前文件执行”’目前b是原始的对象,可以访问find_element_by_id之类的原始函数bk是封装好的对象,可以访问自己定义的方法,也可以链式.不过访问一次指针就变化一次,访问attr/text可以重置,访问其他函数指针就变了,可以调用属性.ini重置指针ini是初始化对象,out是转换成原始的可点击操作的对象,IE要用32位的系统,不然输入会卡顿,点击无效不完美但是可以链式调用!!!!知识点:chrome点击li标签(里面有a链接)可以跳转,但是ie环境确不能跳转,ie需要点击a”’# b=Brower(“https://www.thepaper.cn/searchResult.jsp”,”IE”)starttime=time.perf_counter()# b=chrome(‘https://www.w3school.com.cn/’,t=5)b=chrome(‘https://www.runoob.com/try/try.php?filename=tryhtml_basic_link’,t=5)bk=Bsl(b)”’这里采用原生的方法试试”’# print(b.title)# print(b)# b.find_element_by_id(“navsecond”).find_elements_by_link_text(“HTML”)[0].click()# b.byid(“intro”).byatexts(“现在开始学习 HTML”)[0].click()# b.toframe(“iframeResult”)# b.bytagname(“a”).click()# b.switch_to_window()# b.byclasses(“item-top”)[3].click()# b.quit()# b.find_element_by_id(“intro”).find_element_by_link_text(“现在开始学习 HTML”).click()# print(b)# b.find_element_by_id(“tpn”).find_element_by_class_name(“next”).find_element_by_tag_name(“a”).click()# b.find_element_by_link_text(“HTML 计算机代码”).click()# b.find_element_by_link_text(“HTML 注释”).click()# end# print(bk)# print(b.title)# print(bk.pagewait(“百度”,b.title,waittime=2))# print(bk.byid(“s-top-left”).find_element_by_link_text(“地图”).get_attribute(“outerHTML”))# x=b.get_window_position()”’ ”’# print(b.title)# bk.todefault()# bk.toframe(“iframeResult”).bytagname(“body”).bytagname(“a”).out.click()# x=bk.ini.byclasses(“item-top”).out# print(x)print(“程序一共耗时:{}秒”.format(time.perf_counter()-starttime))# print(bk)#链式调用查找元素# s=bk.byid(“navsecond”).bytagname(‘ul’).atext(‘CSS’).text# print(s)#上一步有了text属性指针已经重置,下一个移动指针# bk.byid(“navsecond”)# x=8#上一个移动指针了,如果想要调用方法查找属性必须ini初始化对象指针# x=bk.ini.byid(“x”).out#.out属性是将对象return self.b转换为可调用原生find_element方法的指针# y=b.find_element_by_id(“x”)# print(y)# js=’document.getElementById(“h”).click();’# bk.runjs(js)# bk.ini.byid(“navsecond”).bytagname(‘ul’).bytagname(‘li’).out.send_keys(Keys.ENTER)# bk.ini.atext(‘现在开始学习 HTML’).out.click()# y=b.find_element_by_id(“navsecond”).find_element_by_tag_name(‘ul’).find_element_by_tag_name(‘a’).click()# x.click()# print(y)# y.click()# print(x)#重置指针并查找元素,转换原生对象进行点击.此时对象指针还停留在id元素上,只是指针是self.b不能调用类方法# bk.ini.byid(“searched_content”).out.click()#上一步用了out现在的指针已经是指向self.b而不是self自身了,不能链式调用了#此时的指针在输入框所以不用重新查找元素直接out转换为原生对象发送文字即可# bk.out.send_keys(“php”) #用out是为了调原生的方法#定位发送按钮(最后一个-1 input元素)# j=bk.ini.byid(“searchform”).bytagnames(“input”).out[-1]#click()方法返回none# j.click()# sleep(1)# exit()# b.byid(“kw”).send_keys(“keysdkfjk”)# b.byid(‘su’).click()# sleep(5)# x=b.bytagname(‘h3’).text# print(x)# b.runjs(‘window.scrollTo(0,document.body.scrollHeight)’)# print(b.title)# b.close()#默认查找元素是等网页全部加载完毕再进行往下执行,ajax不行,一定要sleep等待# sleep(5)# ok=b.byxpath(“//div[@class=’focus’]//img[@alt=’对称加密和非对称加密’]”).get_attribute(“src”)# print(ok)# #这里图片是ajax,如要等待5s# sleep(5)# ok=b.byxpath(“//div[@class=’focus’]//img[@alt=’对称加密和非对称加密’]”).get_attribute(“src”)# print(ok)# print(b.byclass(‘sc_inp’).get_attribute(‘name’))# print(b.byid(‘sc_inp’).is_displayed())#input元素当然不可见了# print(b.byid(‘sc_inp’).is_enabled())# b.wait().until(lambda x:b.byclass(‘sc_inp’).is_displayed())# print(b.title())# b.close()# print(b.bytagname(‘title’).text)# b.byclasses(“sc_inp”)[0].click()# b.byclass(“sc_inp”).send_keys(‘洛阳’)# sleep(4)# b.byid(‘searchResultForm’).byclasses(‘sc_bt’)[0].click()# # b.byclasses(‘sc_bt’)[0].click()# print(b.byclass(‘sc_bt’).is_enabled())# # b.wait().until(lambda x:b.byclass(“sc_bt”).click())# # b.runjs(‘window.scrollTo(0,document.body.scrollHeight)’)# try:# ok=b.wait(3).until(lambda brower:b.atext(“上海书评”))# print(ok)# except:# b.runjs(‘window.scrollTo(0,document.body.scrollHeight+50)’)# print(“找到元素停止了.”)”’标记常用的用语browser.execute_script(‘window.scrollTo(0,document.body.scrollHeight)’)#下翻到页低WebDriverWait(browser,10).until(lambda browser:browser.find_element_by_id(“kw”)).send_keys(“pytest”)获取属性get-attribute 获取文本.text 点击.click() 发送文本.send_keys(xx)尽量先试用id/class/name等方式进行定位,实在不行再用xpath,xpath有延时find_element_by_class_name 找class只找第一个,找不到报错find_elements_by_class_name 找class返回所有的列表,找不到为空”’
按照上面就可以简写selenium函数并且可以支持链式调用