对UI自动化测试有一点“个人成见”,其实就是和现在工作的情况不相匹配,不适用,因为它需要的条件比较严苛,也就导致了它的使用范围窄,因此此前对selenium模块的探究都是浅尝即止,但是这么强大的东西,不仅可以适用于自动化测试的。(最近发现这个东西烧CPU,电脑开3个,跑了十个小时,cpu直接躺了)
对于爬虫来说,不论是post接口,还是get html,一旦对方做了防爬的措施,都会遭到对方的陷阱,但是对于浏览器端都是用户友好的,通过强大的selenium,对于一些场景,可以做最轻松的爬虫,缺点就是效率有点慢。
做了几个selenium的爬虫程序后,想记录一些小tips,这样可以写一些更加pythonic的代码,并且对自动化UI也是很有帮助的。
一、解耦
由于比起post或者urlopen,selenium和‘猎物’之间多隔了一层UI,那么它的风险就更大,出错就更容易。所以一定要解耦,主函数,登陆,页面,单个操作尽量都分开,做好解耦的工作,后期改动也方便。 代码更加具有阅读性。更重要的是在重试某个步骤的时候,你更加应对自如。
二、错误捕获处理
上面说了,selenium的出错概率很高,不仅是页面经常被攻城狮改,这还和你的本地的网络,内存,CPU息息相关,如果你的浏览器什么都加载不出来,不要怕,做下,常规操作。 在与UI斗智斗勇的时候,最大的本领就是做各种异常处理。from selenium.common.exceptions import 导入各种异常包,常见的有:
NoSuchElementException,NoAlertPresentException,NoSuchFrameException,InvalidSelectorException,IndexError
捕获之后选择重试某个步骤,或者break,continue
三、等待
无法找到html节点为依据的情况下,我们会使用time.sleep,但是能找到依据的情况下,一定要使用selenium.webdriver.support.wait和selenium.webdriver.support提供给我们的WebDriverWait和expected_conditions,避免无谓的等待,提供程序效率,示例:
WebDriverWait(webdriver.Chrome(),20).until(expected_conditions.visibility_of_element_located((By.XPATH,"//*[@id='searchResult']/div/div[1]/label")))
四、重试
错误捕获后我们会有重试,这个可以在函数块中处理,也可以在设计中体现,比如使用队列,生产消费异步处理,多线程避免多进程更耗cpu的问题。
from threading import Thread import time import random from queue import Queue from collections import deque queue = Queue(5) class Pro_Thread(Thread): def run(self): tasks = deque([1, 2, 3]) global queue while True: task = tasks.pop() queue.put(task) print("生产", task) time.sleep(random.random()) class Con_Thread(Thread): def run(self): global queue while True: task = queue.get() queue.task_done() print("消费", task)