selenium api 基本全都会抛异常
比如
if driver.find_element_by_class_name("general-error"): print("登录错误")
必须要写成如下 try: if driver.find_element_by_class_name("general-error"): print("登录错误") except: pass
所有常用 api 都会抛出异常,每个 find_element_by_xxx 都必须放在 try except 封装成函数,显得代码臃肿不堪...
是不是我的风格有问题,请教下大家都怎么处理这种情况的.
循环登录代码
while True:
if driver.find_element_by_class_name("loaderIcon"):
print("网页加载中")
time.sleep(1)
elif driver.find_element_by_class_name("ut-tab-bar"):
print("登陆成功")
return True
elif driver.find_element_by_class_name("btn-standard"):
driver.find_element_by_class_name("btn-standard").click()
WebDriverWait(driver, 1).until(EC.frame_to_be_available_and_switch_to_it((By.ID, "btnLogin")))
if driver.find_element_by_id("btnLogin"):
print("找到 btnLogin")
break
elif driver.find_element_by_id("email"):
driver.find_element_by_id("email").send_keys(username)
driver.find_element_by_id("password").send_keys(pwd)
driver.find_element_by_id("btnLogin").click()
elif driver.find_element_by_id("btnSendCode"):
print("等待输入验证码")
elif driver.find_element_by_class_name("general-error"):
print("登陆错误!!!")
break
必须要吧每个find_element_xxx 封装函数,内部try catch处理,代码量增加不少
while True:
if 是否加载中():
print("网页加载中")
time.sleep(1)
elif 登陆成功():
print("登陆成功")
return True
elif 是否登录界面():
driver.find_element_by_class_name("btn-standard").click()
WebDriverWait(driver, 1).until(EC.frame_to_be_available_and_switch_to_it((By.ID, "btnLogin")))
if driver.find_element_by_id("btnLogin"):
print("找到 btnLogin")
break
elif 是否输入用户名密码界面():
driver.find_element_by_id("email").send_keys(username)
driver.find_element_by_id("password").send_keys(pwd)
driver.find_element_by_id("btnLogin").click()
elif 是否验证码界面():
print("等待输入验证码")
elif 登陆错误(1):
print("登陆错误!!!")
break
1
imn1 2020-11-20 12:32:26 +08:00
这种情况我选择换个写法,例如其他模块
实际上我都没用过 selenium api,都不知道会抛出异常,我是获取 content 然后用其他 parser 模块处理的 如果不可避免非要用某个模块,它又容易抛出异常,我会写个类继承过来,或者闭包,把异常集中处理 |
2
happinessnch 2020-11-20 12:37:47 +08:00
异常处理,和业务逻辑没有关系,咋一看好像很臃肿,好多地方要 try catch,
实际上异常处理多了慢慢也就习惯了,根据不同异常做一些定制化的处理, 绝大多数异常是不应该直接 pass 的,但是实际开发时,每个异常都处理确实有点过于苛求了。 |
3
no1xsyzy 2020-11-20 14:25:40 +08:00
这个是设计问题,不过你这边似乎也可以更正交地抽象
def finds(driver, **kwargs): try: return driver.find_element(...) # TODO: implement it except: return None 这样的话你以后就可以 if finds(driver, class_name="loaderIcon"): ... elif finds(driver, class_name="ut-tab-bar"): ... ... |
4
no1xsyzy 2020-11-20 14:28:58 +08:00
@happinessnch BTW 如果逻辑上确实应不处理,我推荐 with contextlib.suppress
如果暂时不作处理,我推荐 except: pass # TODO: handle this |
5
bbxiong OP @no1xsyzy 这种设计方式用起来比较方便,其实我奇怪的为啥 selenium 设计这些 api 要抛异常,而不是找不到返回 None
|
6
imn1 2020-11-20 15:24:16 +08:00
@bbxiong #5
模块一般是通用的,泛考虑 例如某个 exif 模块,里面严格执行 exif 规范,dump 的时候一个值错了就会抛异常 本来 exif 有几百条,一条错误并不影响其他读取,也不影响图片本身显示,批量处理(上千个图片)遇到错误可以跳过就行了,逐个处理异常确实麻烦 但人家按照规范做,也不能说人家做错了,因为遵守规范总是正确立场,只能自己继承修改以适应自己的需求 |
7
no1xsyzy 2020-11-20 22:38:38 +08:00
@bbxiong 发现我可能单位写了一堆忘了发……
应该它的这些 API 就是设计为链式调用的,那显然报一个“元素找不到”的错比“NoneType 没有此属性”的错更合理。 不过,我设计的话会设计两套 API,一个更简洁的引发异常,更啰嗦的给 None,形如 dct['key'] v.s. dct.get('key') 或者提供一个参数来表示默认值,不提供就引发异常,形如 dct.pop('key', None) v.s. dct.pop('key') |
8
peckey 2020-11-25 19:24:09 +08:00
find_elements_by_xxx 不会抛出异常
|