
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 然后用其他 prser 模块处理的 如果不可避免非要用某个模块,它又容易抛出异常,我会写个类继承过来,或者闭包,把异常集中处理 |
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 不会抛出异常 |