浏览器自动化操作——selenium

前言

在工作日常流程中,有这样一步:将信息内容同步至某一网站。其实是一个比较简单的工作,但每次都由人工同步,就比较枯燥且费时。为了优化工作流程,提高工作效率,笔者就打算从模拟浏览器操作的思路出发,自动化完成这一工作。(当然,还有其他思路:如利用get或post等方式传参,但正好想接触一下这方面的知识,于是采用上面那种思路啦!)

selenium介绍

以下内容节选自百度百科:

Selenium [1] 是一个用于Web应用程序测试的工具。Selenium测试直接运行在浏览器中,就像真正的用户在操作一样。支持的浏览器包括IE(7, 8, 9, 10, 11),[Mozilla Firefox](https://baike.baidu.com/item/Mozilla Firefox/3504923),SafariGoogle ChromeOpera等。这个工具的主要功能包括:测试与浏览器的兼容性——测试你的应用程序看是否能够很好得工作在不同浏览器和操作系统之上。测试系统功能——创建回归测试检验软件功能和用户需求。支持自动录制动作和自动生成[ .Net](https://baike.baidu.com/item/ .Net/156737)、JavaPerl等不同语言的测试脚本。

简而言之,selenium能模拟用户对浏览器的操作,是一种帮助测试的工具。

但本次笔者使用selenium是作为信息同步自动化的工具。

定位关键

xpath

  • 介绍

    • XPath(XML Path Language),即为XML路径语言。它基于XML的树状结构,能用来定位XML文档中元素的位置。
  • 获取方法

    • 进入浏览器,f12,定位到相关元素,右键选择‘复制xpath‘,即可粘贴使用。
  • 实例

    • //*[@id=”search”]

具体xpath的语法,读者可直接百度搜索。

css selector

  • 介绍

    • XPath(XML Path Language),即为XML路径语言。它基于XML的树状结构,能用来定位XML文档中元素的位置。
  • 获取方法

    • 进入浏览器,f12,定位到相关元素,右键选择‘复制xpath‘,即可粘贴使用。
  • 实例

    • //*[@id=”search”]

基本语法

在找到两种基本的定位方法之后,就可以使用下面几种方式对相关元素进行操作。

其实语法都比较简单,关键是要找准定位。

传参数传值

1
2
browser.find_element(By.XPATH, "//input[@type=\'text\']").send_keys("xxxxxxx")
browser.find_element(By.CSS_SELECTOR, "td:nth-child(2) > input").send_keys("xxxxxxx")

点击按钮

1
2
browser.find_element(By.XPATH, "/html/body/div/div/div/div[1]/form/div[4]/div/div/button").click()
browser.find_element(By.CSS_SELECTOR, ".submit").click()

上传文件

基于python的selenium的文件上传方式主要是两种:input标签上传、非input标签上传

一般情况下,上传文件的按钮中都会带上input的标签,也就是第一种。这种方式可以直接输入文件路径,再调用send_keys直接输入路径来完成文件上传的操作。具体代码如下:

1
2
file_path = 'E:\\xxxxx\\xxxxx\\xxxxx.pdf'
browser.find_element_by_class_name("files_upload_btn").send_keys(file_path)

但在此次实践过程中,笔者当时遇到了上传文件标签为div的情况,也就是第二种:非input标签上传

在这种情况下,文件上传按钮的标签可能是a或者div等等,在点击按钮之后会跳出新的对话框进行文件上传。而这个新的对话框是很难用selenium识别捕捉的。对于这第二种情况,目前的解决思路主要是利用外部工具定位元素+利用pywin32模拟键盘操作。在此不做赘述。

遇到的问题

网站登录跳转

由于该网站的特殊性,在进入主要网站之前会有一个vpn登陆的网站。但在实际操作时,不同浏览器反应不同。比如Chrome会自动下载一个插件,Firefox会弹窗警告无法下载,这两个操作完成后能点击进入主要网站。由于实际情况下,弹窗上的元素是比较难以捕捉的,所以当时在这上面花费了比较久的时间。

最终的解决办法是:在登录vpn后,直接发起对主要网站的请求。这样就跳过了弹窗和点击进入的两个动作。

为何可以这样做呢,是因为在两次请求的时间内,用户的cookie与session是保留的。

验证码

在登录主要网站时,登录框中有一项验证码。笔者当时想直接利用python的验证码识别库tesserocr,但试验之后发现准确率较低。于是最终让程序预留一个input,人工输入验证码。

xpath定位出错

这个问题其实比较玄学。告诉我们2个道理:不要轻信浏览器的复制粘贴+细心观察。有时间可以研究一下xpath与css路径的原理。最终是通过观察标签结构,发现相邻下拉框的div数组下标是连续相邻的,故而根据规律进行填写。

下拉选择框

在下拉选择框的备选项过多时,会超出下拉框的长度。如果你要选择的选项在末尾,那么操作的时候就需要进行下滑才能进行选定。

一般情况下,选择框会用select标签,然后用option标签中的value属性来设定其中的选项。这种情况就很好操作:先定位下拉框,再定位选项。

但是在本次的实践中发现该网站的选择框是在div里面嵌套ul的,然后将选项卸载li中。所以上面说到的方法不再适用。

最后的解决方法是:先定位到选择框的ul一层,再对ul中的li的值进行遍历匹配。具体代码如下:

1
2
3
4
5
6
browser.find_element_by_xpath("/html/body/div[2]/div/div[2]/div/form/div/div[4]/div[5]/div[1]/div/div/div/div[1]/input").click()
lis = browser.find_elements_by_xpath("/html/body/div[12]/div[1]/div[1]/ul/li")
for li in lis:
if "你要找的值" in li.text:
li.click()
break

总结

本次的代码之旅还是比较轻松的,可能是之前的前端还是有点基础。其实用selenium的方法来解决此次的需求可能是比较不智能的,但就当做是一次涉猎吧,总的说来还是有不少收获的。希望之后要在写代码的过程中就及时记录遇到的问题(但这样写出来可能就会过于详细了)。之后可能会看看手机上的相关操作。

继续学习,继续努力!