Selenium踩坑记
背景故事
最近因为一些原因,帮LXC同学和老谢写了两段Python脚本来辅助工作。
于是就用到了Selenium,这个库本是用于前端自动化测试的,嘛,用来做浏览器重复操作也是可以的。
这里就来说说踩过的坑,以备后查。
写完有一段时间了,快忘利索了,23333.
正文
一、表单问题
有些网页表单是两层html嵌套的,操作元素时要使用:
1 2 |
driver.switch_to.frame(Tinymce) driver.switch_to_default_content() |
来进行切换,否则会出现找不到页面元素的情况。
二、执行JS
执行js分为同步执行和异步执行两种。
execute_script
同步执行,会阻塞主线程执行,直到js代码执行完毕。有返回值,如下:
-
- 如果返回一个页面元素(document element), 这个方法就会返回一个WebElement
- 如果返回浮点数字,这个方法就返回一个double类型的数字
- 返回非浮点数字,方法返回Long类型数字
- 返回boolean类型,方法返回Boolean类型
- 如果返回一个数组,方法会返回一个List
- 其他情况,返回一个字符串如果没有返回值,此方法就会返回null
execute_async_script
异步执行,不会阻塞主线程执行
三、Drvier的坑
Selenium还是支持不少的浏览器,Edge、Chrome、Firefox、Safari、Phantomjs都支持。但不推荐使用Phantomjs,个人使用当中感觉不是很稳定,如果页面是JS渲染出来的内容,经常是空白页面。
基本上最常用的还是Firefox和Chrome。
下载Drvier的时候需要注意要和本机上已经安装的浏览器版本号相匹配。
指定Driver的位置:
1 |
Driver = webdriver.Firefox(executable_path='') |
SSL的问题
在使用Firefox的过程中,又遇到调试反复出现不信任证书的问题,研究了一下发现每次启动Driver,都会生成一个新得Profile,所以添加一次安全例外后关闭程序重新执行又会出现证书不信任的问题。
可以这样解决:
1.Win+R打开运行窗口,输入firefox -p,打开Firefox的配置文件管理器,新建一个配置文件。
名字随意取,文件夹选择到一个好找的地方就可以了。
2.随后启动Firefox,将证书导入进去。
3.将新建的配置文件整个文件夹复制出来。
4.添加如下代码:
1 2 3 4 |
profile = webdriver.FirefoxProfile("profile文件夹路径+文件夹名称") Driver = webdriver.Firefox(profile) #若需要指定Drvier位置,如下: Driver = webdriver.Firefox(profile,executable_path='lib/geckodriver') |
代理的问题
浏览器代理的设置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
from selenium.webdriver.common.proxy import * MyProxyIP = 代理IP MyProxyPort = 代理端口 profile = webdriver.FirefoxProfile() profile.set_preference('network.proxy.type', 1) profile.set_preference('network.proxy.http', MyProxyIP) profile.set_preference('network.proxy.http_port', MyProxyPort) profile.set_preference('network.proxy.ssl', MyProxyIP) profile.set_preference('network.proxy.ssl_port', MyProxyPort) profile.set_preference('network.proxy.socks', MyProxyIP) profile.set_preference('network.proxy.socks_port', MyProxyPort) profile.set_preference('network.proxy.ftp', MyProxyIP) profile.set_preference('network.proxy.ftp_port', MyProxyPort) profile.update_preferences() Driver = webdriver.Firefox(profile,executable_path='lib/geckodriver') |
等待
等待浏览器页面加载或渲染,有这么几种方式:
1.显式等待
1 2 3 4 5 6 7 8 |
from selenium.webdriver.common.action_chains import ActionChains from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By element = WebDriverWait(Driver, 60).until( EC.presence_of_element_located((By.ID, "overview")) ) |
这种等待方式就是间隔一段时间去检测某元素是否存在,上面代码就是60秒内间隔500ms检测ID为overview的元素是否存在,超过60秒检测不到就抛出一个异常。
不一定要使用元素ID,Class、Xpath都可以。参见官方手册:
https://seleniumhq.github.io/selenium/docs/api/py/webdriver/selenium.webdriver.common.by.html
2.隐式等待
通过文档,隐式等待看上去就是设置了一个Driver超时时间,大D写那两段Python代码的时候并没有用到,后面用了再来补充好了。
3.线程休眠
这应该是最蠢的办法了。
1 |
time.sleep(10) |