我就奇怪怎么分割线以下那段代码时灵时不灵,原来是我自己修改的时候,思路弄错了。
涉及到try-return-except结构中的一些功能效果。
废话不多说,先上修改后的代码:
def safe_get_element(driver,by,element_num,timeout=2):
"""
传参时:
1,driver参数为浏览器驱动所在变量名,下方return部份不需要修改。
2,by参数和element_num参数参照driver.find_element("","")的写法,简略版如下,详细版请参照https://blog.csdn.net/qq_32897143/article/details/80383502
2.1,by_id -> find_element("id","")
2.2,by_xpath -> find_element("xpath","")
2.3,by_link_text -> find_element("link text","")
2.4,by_partial_text -> find_element("partial link text","")
2.5,by_name -> find_element("name","")
2.6,by_tag_name -> find_element("tag name","")
2.7,by_class_name -> find_element("class name","")
2.8,by_css_selector -> find_element("css selector","")
感谢CSDN博客ID为“我的猪很厉害的”的相关分享。
3,timeout参数默认为5,以秒为单位
4,将会返回一个元素,
4.1,后续操作与driver.find_element("id","kw").send_keys('python')等一样,
4.2,参考:safe_get_element(driver=amzjp,by='id',element_num='drrGenerateReportButton').click()
"""
import time
start_time = time.time()
print('开始时间为:{0:F}'.format(start_time))
while True:
try:
print('开始定位元素,当前时间为:{0:F}'.format(time.time()))
element_result=driver.find_element(by,element_num)
return element_result
except:
if time.time() - start_time >= timeout:
print('定位元素超时,当前时间为:{0:F}'.format(time.time()))
return False
else:
time.sleep(0.2)
print('正在定位元素,当前时间为:{0:F}'.format(time.time()))
def safe_get_elements(driver,by,element_num,timeout=2):
"""
该自定义函数会返回一个由元素组成的列表,寻找所需要的元素时,请参照列表的方式取出元素。
传参时:
1,driver参数为浏览器驱动所在变量名,下方return部份不需要修改。
2,by参数和element_num参数参照driver.find_element("","")的写法,简略版如下,详细版请参照https://blog.csdn.net/qq_32897143/article/details/80383502
2.1,by_id -> find_elements("id","")
2.2,by_xpath -> find_elements("xpath","")
2.3,by_link_text -> find_elements("link text","")
2.4,by_partial_text -> find_elements("partial link text","")
2.5,by_name -> find_elements("name","")
2.6,by_tag_name -> find_elements("tag name","")
2.7,by_class_name -> find_elements("class name","")
2.8,by_css_selector -> find_elements("css selector","")
感谢CSDN博客ID为“我的猪很厉害的”的相关分享。
3,timeout参数默认为5,以秒为单位
4,将会返回一个元素,
4.1,后续操作与driver.find_elements("id","kw")等一样,例:driver.find_elements("css selector",".mnav")[6].click()
4.1.1,class一般是用.标记
4.1.2,id一般是用#标记
4.2,参考:safe_get_elements(driver=amzjp,by='id',element_num='drrGenerateReportButton')
"""
import time
start_time = time.time()
print('开始时间为:{0:F}'.format(start_time))
while True:
try:
print('开始定位元素,当前时间为:{0:F}'.format(time.time()))
element_result_list=driver.find_elements(by,element_num)
return element_result_list
except:
if time.time() - start_time >= timeout:
print('定位元素超时,当前时间为:{0:F}'.format(time.time()))
return False
else:
time.sleep(0.2)
print('正在定位元素,当前时间为:{0:F}'.format(time.time()))
以上为修改后的代码,目前timeout功能可以正常运作了。
区别在于:
原版代码中我图省事,直接把find_element放在了return后面,这相当于return了一个“任务”,而不是return一个“结果”。
新版代码中,我把find_element放在了try的后面,而放在return的前面,并且使用了一个变量,对find_element的结果进行接收,而return则只返回已经被变量接收的元素这一“结果”,而不再是find_element这个“过程”。
所以就能运作成功了。
如果感兴趣原版本(错误版本)的话,可以继续往下看。
如果只是找个方法解决一下元素定位时间过久,或者在定位不到元素的时候也不想让程序报错退出,看到这里就可以了。
PS:再提醒一句,修正后的代码,如果找不到元素,会返回False哦~
如果希望继续报错的话,把函数中的“return False”改成“raise Exception(‘没有找到元素’)”就好~
以上~
感谢观看~
m(_ _)m
~~~~~~~以上为2020-09-07新增内容,以下为原来的文章~~~~~~~~
这其实算是我上课之后的收获吧,听了康神的爬虫课,get了这么个技能。
这里厚颜无耻地链上康神的博客哈~康神的CSDN博客地址
实际上我在使用链式编程解决“将日常工作自动化”的需求时发现,selenium包里面的元素定位(selenium原装的元素定位方法,参照博文《史上最全!Selenium元素定位的30种方式》),偶尔会出现卡在那里不动的情况,而且如果页面不存在需要定位的元素时,卡顿往往会超过1分钟,这就很难熬了。
结合康神上课时给出的代码,稍加改良,就得出来下面这两个safe_get元素的自定义函数了。
其实不难看出,这两个自定义函数,对应的分别是find_element_by和find_elements_by,获得的也是一个是元素,一个是由元素组成的列表。
效果差不多,但加上了timeout(默认为2秒)。
8种对应写法,来源也在函数说明里写上了。
上代码:
def safe_get_element(driver,by,element_num,timeout=2):
"""
传参时:
1,driver参数为浏览器驱动所在变量名,下方return部份不需要修改。
2,by参数和element_num参数参照driver.find_element("","")的写法,简略版如下,详细版请参照https://blog.csdn.net/qq_32897143/article/details/80383502
2.1,by_id -> find_element("id","")
2.2,by_xpath -> find_element("xpath","")
2.3,by_link_text -> find_element("link text","")
2.4,by_partial_text -> find_element("partial link text","")
2.5,by_name -> find_element("name","")
2.6,by_tag_name -> find_element("tag name","")
2.7,by_class_name -> find_element("class name","")
2.8,by_css_selector -> find_element("css selector","")
感谢CSDN博客ID为“我的猪很厉害的”的相关分享。
3,timeout参数默认为5,以秒为单位
4,将会返回一个元素,
4.1,后续操作与driver.find_element("id","kw").send_keys('python')等一样,
4.2,参考:safe_get_element(driver=amzjp,by='id',element_num='drrGenerateReportButton').click()
"""
import time
start_time = time.time()
print('开始时间为:{0:F}'.format(start_time))
while True:
try:
print('开始定位元素,当前时间为:{0:F}'.format(time.time()))
return driver.find_element(by,element_num)
except:
if time.time() - start_time >= timeout:
raise Exception('没有找到元素')
print('定位元素超时,当前时间为:{0:F}'.format(time.time()))
else:
time.sleep(0.2)
print('正在定位元素,当前时间为:{0:F}'.format(time.time()))
def safe_get_elements(driver,by,element_num,timeout=2):
"""
该自定义函数会返回一个由元素组成的列表,寻找所需要的元素时,请参照列表的方式取出元素。
传参时:
1,driver参数为浏览器驱动所在变量名,下方return部份不需要修改。
2,by参数和element_num参数参照driver.find_element("","")的写法,简略版如下,详细版请参照https://blog.csdn.net/qq_32897143/article/details/80383502
2.1,by_id -> find_elements("id","")
2.2,by_xpath -> find_elements("xpath","")
2.3,by_link_text -> find_elements("link text","")
2.4,by_partial_text -> find_elements("partial link text","")
2.5,by_name -> find_elements("name","")
2.6,by_tag_name -> find_elements("tag name","")
2.7,by_class_name -> find_elements("class name","")
2.8,by_css_selector -> find_elements("css selector","")
感谢CSDN博客ID为“我的猪很厉害的”的相关分享。
3,timeout参数默认为5,以秒为单位
4,将会返回一个元素,
4.1,后续操作与driver.find_elements("id","kw")等一样,例:driver.find_elements("css selector",".mnav")[6].click()
4.1.1,class一般是用.标记
4.1.2,id一般是用#标记
4.2,参考:safe_get_elements(driver=amzjp,by='id',element_num='drrGenerateReportButton')
"""
import time
start_time = time.time()
print('开始时间为:{0:F}'.format(start_time))
while True:
try:
print('开始定位元素,当前时间为:{0:F}'.format(time.time()))
return driver.find_elements(by,element_num)
except:
if time.time() - start_time >= timeout:
raise Exception('没有找到元素')
print('定位元素超时,当前时间为:{0:F}'.format(time.time()))
else:
time.sleep(0.2)
print('正在定位元素,当前时间为:{0:F}'.format(time.time()))
后续其实也碰上了一点问题,就是没办法写成像find_element那样的链式定位:driver.find_element_by_id(‘123’).find_element_by_id(‘456’).click()
但可以这样使用:
driver=webdriver(r’我是浏览器驱动绝对路径’)
driver.get(‘我是一个网址’)
element_big=safe_get_element(driver=driver , 别的参数)
element_in_big=safe_get_element(driver=element_big , 别的参数).click()
当然,如果excel嵌套用得6,也可以尝试直接把element_big那一段写入到element_in_big的driver参数里。。
只不过这样的话你这一行代码会很长就是了。。
在此再次感谢康神提供思路~
康神的CSDN博客地址
#~~~~~~~我是分割线,以下为200828更新内容~~~~~~~~
更新一个版本,引入了selenium的NoSuchElementException块。
修改了except部份,使得程序即便无法定位到元素,也不会因为报错导致整个程序中止运行,而是返回了一个False。
def safe_get_element(driver,by,element_num,timeout=2):
"""
传参时:
1,driver参数为浏览器驱动所在变量名,下方return部份不需要修改。
2,by参数和element_num参数参照driver.find_element("","")的写法,简略版如下,详细版请参照https://blog.csdn.net/qq_32897143/article/details/80383502
2.1,by_id -> find_element("id","")
2.2,by_xpath -> find_element("xpath","")
2.3,by_link_text -> find_element("link text","")
2.4,by_partial_text -> find_element("partial link text","")
2.5,by_name -> find_element("name","")
2.6,by_tag_name -> find_element("tag name","")
2.7,by_class_name -> find_element("class name","")
2.8,by_css_selector -> find_element("css selector","")
感谢CSDN博客ID为“我的猪很厉害的”的相关分享。
3,timeout参数默认为5,以秒为单位
4,将会返回一个元素,
4.1,后续操作与driver.find_element("id","kw").send_keys('python')等一样,
4.2,参考:safe_get_element(driver=amzjp,by='id',element_num='drrGenerateReportButton').click()
"""
from selenium.common.exceptions import NoSuchElementException;import time;
start_time = time.time()
print('开始时间为:{0:F}'.format(start_time))
while True:
try:
print('开始定位元素,当前时间为:{0:F}'.format(time.time()))
return driver.find_element(by,element_num)
except NoSuchElementException as e:
if time.time() - start_time >= timeout:
#打印异常信息
print(e,'判断结束,没有找到该元素,判断耗时:{}'.format(time.time()-start_time))
#发生了NoSuchElementException异常,说明页面中未找到该元素,返回False
return False
else:
time.sleep(0.2)
print('正在定位元素,当前时间为:{0:F}'.format(time.time()))
各位看官请按照实际需要选择使用哈~