这些天踩过的selenium的坑

简介: 不得不说,selenium是1个很不错的Web自动化工具,提供了多种语言的支持,其中包括Python、Ruby、Java、Nodejs等。但不得不说,随着对该工具使用的越来越多,就会发现它存在的一些不足甚至有待改进的地方。而对该工具的使用,还得追溯到几年前信息采集的1个项目,当时是赚点人品学习了一下,并没有太深入的使用。而这次,为了项目的1个需求,深入的挖掘并进行总结,希望给后来的人抛砖引玉,减少走弯路。


前言

不得不说,selenium是1个很不错的Web自动化工具,提供了多种语言的支持,其中包括Python、Ruby、Java、Nodejs等。但不得不说,随着对该工具使用的越来越多,就会发现它存在的一些不足甚至有待改进的地方。

而对该工具的使用,还得追溯到几年前信息采集的1个项目,当时是赚点人品学习了一下,并没有太深入的使用。而这次,为了项目的1个需求,深入的挖掘并进行总结,希望给后来的人抛砖引玉,减少走弯路。



适应人群

这篇文章写给有志于从事如下岗位工作的人群:

  • Web自动化测试
  • 信息安全开发
  • 爬虫工程师
  • 打算找份Python工作

说完了题外话,下面我们还是讲讲实际的操作。这里以Python为例进行说明。


找不到浏览器执行文件

在selenium高版本中,比如3.141中,即使你不指定浏览器的位置,selenium也是可以找到其位置,这是让自己觉得神奇的地方。当然,为了保险起见,还是把对应的浏览器可执行文件及相关的驱动放在环境变量PATH目录下吧。

如果实在找不到浏览器可执行文件,那么可以通过下面的方式进行指定,以火狐为例:


from selenium.webdriver.firefox.firefox_binary import FirefoxBinary
binary = FirefoxBinary("E:/Program Files/Mozilla Firefox/firefox.exe")
browser = webdriver.Firefox(firefox_binary=binary)

我们需要导入FirefoxBinary类,然后对其进行实例化,传入的参数是你本地系统上安装的绝对路径,最后将其作为 firefox_binary参数传递给Firefox构造器。



浏览器无任何反应

如果上面的找不到浏览器执行文件是个小坑的话,那么这里的浏览器无任何响应可以说就是个隐形的陷阱。你会神奇的发现,当你把selenium、浏览器及对应驱动,如chromedriver、geckodriver都安装了,但是当浏览器执行到这一行:

browser = webdriver.Firefox()
browser.get("https://www.baidu.com")

结果等了10秒,浏览器还是空白的一片。正常不是应该访问百度的首页吗?怎么不跳转呢,然后什么异常或者提示都没有。

当你遇到这样的情况,那么你就要静下心来先想一下,你当前的浏览器版本是多少?浏览器的驱动是多少?还有你的selenium库的版本是多少?

自己遇到1个问题就是,公司PC上安装的上述版本如下:

selenium = 2.53
Firefox = 56.0
geckodriver = 0.19

按照常理,它是可以正常运行的,但是结果就是大半天都没响应。实际上,上述的版本中火狐版本56.0与selenium的版本是不兼容的,必须升级selenium库。

你需要记住的是,selenium的版本2.53最多只能支持到版本54即可,而geckodriver版本0.19是支持火狐55以上的。


访问的URL的请求获取

解决完或者逃过了上述2个问题后,对于业务需要获取访问的URL地址的请求的问题,可以说还是有难度的。但是,还是有解决方案的。

对于Python3来说,真的很简单。直接pip安装selenium-wire就好了,该库要求Python版本大于3.4,这完全可以说就不是事情。而很不幸,公司的项目采用的是Python2.7开发的,对于这样的问题,实际上有多种解决方案,这里简单的说下通过代理的方式。

最开始,公司方面使用的是proxy2这个库来获取其请求,其实际上通过Python标准库中的BaseHTTPServer和ThreadMixin来实现1个简易的代理。但是后来在实践中发现,该库存在3个不足的地方:

  • 会出现偶尔获取不了HTTPS请求包
  • HTTPS包即使能获取到但是很容易出现异常
  • 并发情况下直接请求很明显就是不对的

然后又选择了1个使用Tornado的toproxy的库,然而该库对于HTTPS的支持还是存在问题,而且要与项目集成也不容易。

最后,选择了1个Java编写的代理browsermob-proxy。对于该库,需要说的是,在pip安装时包的名称是 browsermob-proxy而不是 browsermobproxy,否则你会发现与网上的教程根本不是同一个事情。


代理竟然没有效果

选择好代理后,接下来就应该为浏览器设置代理了,不然是没有办法截取到HTTP请求信息的。然而,对于Chrome浏览器而言,常用的如下方式是完全无效的:

option = ChromeOptions()
option.add_argument("--proxy-server=localhost:8080")

这是网上99%教程的写法,然而对于公司PC上版本只有60的Chrome浏览器而言,基本无视。

而如果将上述代码修改为如下:

proxy = Proxy({
   "httpProxy":"localhost:8080",
   "sslProxy":"localhost:8080"
})

那么这种方式,就可以正常的获取到对应的URL请求的信息。



HTTPS证书不可用

好不容易把浏览器代理给设置好了,接着可以心想总算可以放心获取请求的信息了。结果对于HTTPS的站点页面,那么浏览器弹出当前站点不可信,浏览器拒绝连接。要么,获取到的信息是请求CA证书站点的。

对于浏览器弹出当前站点不可信的问题,可以直接让浏览器不验证证书的安全性。而对于获取到请求CA证书站点信息的问题,对于火狐浏览器而言,需要手动创建1个Profile,可以在关闭浏览器的情况下,重要的话要重复3遍。

在浏览器关闭的情况下,运行下面的命令:

firefox.exe -p

此时弹出如下的页面:


65.jpg

然后创建1个配置文件,这里假设为xxx,并在创建浏览器的时候进行指定:

profile = webdriver.FireforxProfile("xxx")
browser = webdriver.Firefox(firefox_profile=profile)


节点遍历时的坑

总算解决了上面琐碎的问题后,总可以安心编码,赶紧弄完,回家躺着。每天熬夜,被项目经理催着是种煎熬。然而,当自己在代码中有如下代码时:

href = browser.find_elements_by_tag("a")
for href in href:
   href.click()

然后就直接出来个 StaleElementReferenceException的异常,直接翻译的话就是对应元素的引用不新鲜了。另外,还有2个常见的异常就是NoSuchElementException和ElementNoVisbleException,通俗的说就是元素找不到和看不到了。

对于这些问题,要根据业务进行取舍,对于后两者,如果业务不是很重要,可以直接跳过当前节点的点击。 而对于StaleElementReferenceException这个异常,只能在每次点击之前重新获取该节点,换句话说,需要这样进行操作:

href = browser.find_elements_by_tag("a")
l = len(href)
for i in range(l):
   href = browser.find_elements_by_tag("a")[i]
   href.click()

这样就可以点击所有的a标签的链接了。



浏览器的Headless与Linux的code=1退出

总算写完基本的逻辑,部署完就可以回家休息了。而在Linux上直接运行不到2分钟就直接code=1的异常退出,异常类似如下:

... can not kill an existed process

对于这样的异常,90%是没有开启浏览器的Headless模式,导致selenium异常退出。
此时,可以通过如下2种方法来开启Headless模式:

option = FirefoxOption()
option.add_argument("-headless")  #方法一
option.headless = True            #方法二

这样上述的问题就可以完美的解决了。



结语

经过1个星期加班加点的工作,总算把selenium的工作可以告一段落了。不得不说,selenium代码接口更新迭代很快,网上很多教程说的也是云里雾里,没少走弯路。

而官方文档的描述更是寥寥几字,很多情况下还是查看其实现的源码可知道来龙去脉,才可以适当的进行修改。

但是,selenium真的是个不错的工具,至少减轻了些琐碎的操作。

对于Python的相关API可以参考:

https://seleniumhq.github.io/selenium/docs/api/py/api.htmlhttps://selenium-python.readthedocs.io/

参考文章:

https://stackoverflow.com/questions/45949274/setting-proxy-in-selenium-in-python-for-firefox-geckodriverhttps://stackoverflow.com/questions/52534658/webdriverexception-message-invalid-argument-cant-kill-an-exited-process-withhttps://www.cnblogs.com/baihuitestsoftware/articles/7753583.html

本文作者:风中纸鹞,1个多年滚打于Web开发的研发工程师。熟悉PHP、Java、C++等编程语言,以编程作为乐趣。

声明:本文为 脚本之家专栏作者 投稿,未经允许请勿转载。

相关文章
|
5月前
selenium 实战
selenium 实战
27 0
|
3月前
|
数据采集 Web App开发 前端开发
Python爬虫之自动化测试Selenium#7
Selenium基本使用、查找结点、节点交互、动作链、获取节点信息、延时等待、前进后退、Cookies、选项卡管理、异常处理【2月更文挑战第26天】
46 1
Python爬虫之自动化测试Selenium#7
|
9月前
|
JavaScript 前端开发
面试官问你selenium元素定位不到有哪些情况?一文讲明白
面试官问你selenium元素定位不到有哪些情况?一文讲明白
68 0
|
12月前
|
数据采集 Python
Python爬虫-selenium
Python爬虫-selenium
|
12月前
|
API
selenium的简单实用以及实战
selenium的简单实用以及实战
|
程序员 C++ Python
730.离线安装selenium过程中踩的三个大坑
730.离线安装selenium过程中踩的三个大坑
|
前端开发 JavaScript 程序员
767.【技术】selenium元素定位踩坑指南(一)
767.【技术】selenium元素定位踩坑指南(一)
|
存储 IDE Java
软件测试|web自动化测试神器playwright教程(八)
软件测试|web自动化测试神器playwright教程(八)
224 0
|
设计模式 测试技术 API
软件测试|web自动化测试神器playwright教程(十)
软件测试|web自动化测试神器playwright教程(十)
368 0
|
Web App开发 JavaScript 测试技术
软件测试|web自动化测试神器playwright教程(一)
软件测试|web自动化测试神器playwright教程(一)
461 1
软件测试|web自动化测试神器playwright教程(一)