06、Selenium的使用
Selenium 是一个自动化测试工具,利用它可以驱动浏览器执行特定的动作,如点击、下拉等操作,同时还可以获取浏览器当前呈现的页面的源代码,做到可见即可爬。对于一些 JavaScript 动态渲染的页面来说,此种抓取方式非常有效。
由于新版Chrome 已经支持无头模式可以替换PhantomJS,下面仅以 Chrome 为例:
获取单个节点的方法
下面我们希望可以访问淘宝页面并进行搜索
可以发现,它的 id 是 q,name 也是 q。则可以通过find_element_by_name() 和find_element_by_id() 或 XPath、CSS 选择器获取该节点。
从结果可以看到这四种方式获取到的节点完全一致。
另外,Selenium 还提供了通用方法 find_element(),它需要传入两个参数:查找方式 By 和值。实际上,它就是 find_element_by_id() 这种方法的通用函数版本,比如 find_element_by_id(id) 就等价于 find_element(By.ID, id),二者得到的结果完全一致。上面的代码等价于:
07、获取多个节点
如果查找的目标在网页中只有一个,那么完全可以用 find_element() 方法。如果有多个节点,只需要用 find_elements() 方法即可,相对原有的方法多个s。
例如我们想获取淘宝左侧导航条的所有条目:
结果:
find_element() 方法,只能获取匹配的第一个节点,结果是 WebElement 类型。如果用 find_elements() 方法,则结果是列表类型,列表中的每个节点是 WebElement 类型。
08、节点交互
Selenium 可以驱动浏览器来执行一些操作,也就是说可以让浏览器模拟执行一些动作。比较常见的用法有:输入文字时用 send_keys 方法,清空文字时用 clear 方法,点击按钮时用 click 方法。示例如下:
更多交互操作可参考:
https://selenium-python-zh.readthedocs.io/en/latest/api.html#module-selenium.webdriver.remote.webelement
09、动作链与切换Frame
在上面的实例的交互动作中都是针对某个节点执行的。比如,输入框的输入文字和清空文字方法,按钮的点击方法。而动作链操作没有特定的执行对象,比如鼠标拖曳、键盘按键等。
下面实现一个节点的拖曳操作,将某个节点从一处拖曳到另外一处:
依次选中要拖曳的节点和拖曳到的目标节点,接着声明 ActionChains 对象调用其 drag_and_drop() 方法申明拖拽动作,最后调用 perform() 方法执行动作:
更多的动作链可参考官方文档:https://selenium-python-zh.readthedocs.io/en/latest/api.html#module-selenium.webdriver.common.action_chains
网页中有一种节点叫做 iframe,也就是子 Frame,相当于页面的子页面,它的结构和外部网页的结构完全一致。Selenium 打开页面后,它默认是在父级 Frame 里面操作,而此时如果页面中还有子 Frame,它是不能获取到子 Frame 里面的节点的。这时就需要使用 switch_to.frame() 方法来切换 Frame。
结果:
通过 switch_to.frame() 方法切换到子 Frame 里面,然后尝试获取子 Frame 里的 logo 节点(这是不能找到的),如果找不到的话,就会抛出 NoSuchElementException 异常,异常被捕捉之后,就会输出 NO LOGO。接下来,重新切换回父级 Frame,然后再次重新获取节点,发现此时可以成功获取了。
10、执行 JavaScript
例如我们可以通过执行 JavaScript来滑动窗口,或弹出提示:
execute_script() 方法即可执行JavaScript。
11、获取节点信息
通过 page_source 属性可以获取网页的源代码,接着就可以使用解析库(如正则表达式、Beautiful Soup、pyquery 等)来提取信息。
但 Selenium 选择节点返回的 WebElement 类型,也有提取节点信息的方法,不需要使用额外的解析库。
获取属性:
get_attribute() 方法获取知乎发现页面第一张图片的地址:
结果如下:
获取文本值、ID、位置、标签名、大小:
WebElement 节点的 text 属性可以返回对应节点的文本内容,ID、位置、标签名、大小也有相应的属性可以获取:
12、延时等待
有时某些页面有额外的 Ajax 请求,直接获取某些节点可能会有获取失败,这时可以通过延时等待一定时间,确保节点已经加载出来。
等待的方式包括 隐式等待 和 显式等待。
隐式等待
当查找节点而节点并没有立即出现的时候,隐式等待将等待一段时间后再查找 DOM,超过设定时间仍未找到则抛出找不到节点的异常。
用 implicitly_wait() 方法可实现隐式等待:
显式等待:
显式等待指定了一个最长等待时间,在规定时间内加载出要查找的节点,就返回该节点;如果到了规定时间依然没有加载出该节点,则抛出超时异常。相对固定等待时间的隐式等待一般会节省一些等待时间。显式等待简单来说,就是直到元素出现才去操作,如果超时则报异常。隐式等待是每隔一小段时间就去查找一下需要查找的节点,超时仍未找到则抛异常。
显式等待示例:
presence_of_element_located 条件代表节点出现,其参数是节点的定位元组。element_to_be_clickable条件代表节点可点击。
WebDriverWait 对象指定最长等待时间,调用 until() 方法传入要等待的条件。
常见等待条件有:
更多详细的等待条件的参数及用法介绍可以参考官方文档:
https://selenium-python-zh.readthedocs.io/en/latest/api.html#module-selenium.webdriver.support.expected_conditions
13、下拉滚动
有时需要借助滚动条来拖动屏幕,使被操作的元素显示在当前的屏幕上。滚动条是无法直接用定位工具来定位的。Selenium 里面也没有直接的方法去控制滚动条,这时候只能借助 JS 来完成了,可以用 selenium 提供的 execute_script() 方法操作,就可以直接执行 JS 脚本。
通过修改 scrollTop 的值,来定位右侧滚动条的位置,0是最上面,100000是最底部。
前进后退
平常使用浏览器时都有前进和后退功能,Selenium 也可以完成这个操作,它使用 back() 方法后退,使用 forward() 方法前进。示例如下:
14、Cookies
15、选项卡管理
结果
16、异常处理
在使用 Selenium 的过程中,难免会遇到一些异常,例如超时、节点未找到等错误,一旦出现此类错误,程序便不会继续运行了。这里我们可以使用 try except 语句来捕获各种异常。
关于更多的异常类,可以参考官方文档:https://selenium-python-zh.readthedocs.io/en/latest/api.html#module-selenium.common.exceptions
17、无头模式
Chrome 浏览器从 60 版本已经支持了无头模式,无头模式在运行的时候不会再弹出浏览器窗口,它减少了一些资源的加载,也在一定程度上节省了资源加载时间。
我们可以借助于 ChromeOptions 来开启 Chrome Headless 模式,代码实现如下:
通过 ChromeOptions 的 add_argument 方法添加了一个参数 --headless即可开启无头模式, Chrome 窗口就不会再弹出来了。
18、反屏蔽
使用正常的浏览器和Selenium启动一个 Chrome 的有头模式打开如下网址:https://bot.sannysoft.com/。可以看到:
显然Selenium暴露了一些特征,我们需要想办法清除这些信息。
清空webdriver信息的JavaScript代码是:
不过我需要通过CDP(即 Chrome Devtools-Protocol,Chrome 开发工具协议)实现在每个页面刚加载的时候执行 JavaScript 代码,隐藏一些特征信息。
88版本完整解决方案:
实验性功能参数 excludeSwitches的值设为 ['enable-automation']可以关闭Chrome 正在受自动化测试工具控制的提示条,useAutomationExtension设为False则关闭了以开发者模式运行扩展程序。
设置两个普通参数使后续代码能够生效。使用 CDP执行的JavaScript代码是专门用来隐藏 Selenium 或 Pyppeteer的特征的,由puppeteer-extra-plugin-stealth的作者写的extract-stealth-evasions工具生成。
具体生成方法可参考:
puppeteer-extra-plugin-stealth: https://github.com/berstend/puppeteer-extra/tree/master/packages/puppeteer-extra-plugin-stealth
extract-stealth-evasions: https://github.com/berstend/puppeteer-extra/tree/master/packages/extract-stealth-evasions
可直接从https://github.com/kingname/stealth.min.js下载某位大佬已经生成好的。
即使处在无头模式下,也可以隐藏WebDriver信息:
感谢每一个认真阅读我文章的人!!!
作为一位过来人也是希望大家少走一些弯路,如果你不想再体验一次学习时找不到资料,没人解答问题,坚持几天便放弃的感受的话,在这里我给大家分享一些自动化测试的学习资源,希望能给你前进的路上带来帮助。
软件测试面试文档
我们学习必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有字节大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。
视频文档获取方式:
这份文档和视频资料,对于想从事【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!以上均可以分享,点下方小卡片即可自行领取。