Selenium+phantomjs模拟网页自动化操作
N久之前使用这对好伙伴实现支持抓取ajax数据的爬虫,最近有个需求是完全模拟某网站的购物操作,结果这个网站比较奇葩,对于表单中某些文本框、复选框等修改后会触发post操作并更改页面内容,而且这些控件之间还会互相影响,直接使用post方式的话比较困难,于是再次祭出神器:
selenium 和phantomjs,此外还可以尝试selenium-ide。
这里phantomjs2.0版本并没提供编译好的通用Linux版,所以本文依然使用1.9版,但在2.0版上测试通过。
1 | # coding=utf-8 |
如果需要使用代理或有特殊需求,把service_args这行代码取消注释即可。
对于正常的浏览网页或者网上购物来说,最基本的操作不外乎点击按钮、单选框、复选框,填写文本框,选择下拉菜单,示例如下:
1 | driver.get(url) #打开网页 |
至于xpath是我最近接触的第二个觉得可归为”神器”,在使用lxml解析网页时这个语法也是十分有用,这里不细说,有时间专写一个关于xpath的文章。那么万一不会xpath怎么办呢?还有下面的几种方式获取这个元素:
- find_element_by_id
- find_element_by_name
- find_element_by_xpath
- find_element_by_link_text
- find_element_by_partial_link_text
- find_element_by_tag_name
- find_element_by_class_name
- find_element_by_css_selector
至于用法都是一样的,具体看上面的文档链接即可。
类似按钮、链接、单选框、复选框这种元素直接click即可,那么下拉菜单怎么办呢?作者提供了一个select类来简化操作:
1 | from selenium.webdriver.support.ui import Select |
如果想得到这个下拉菜单的值,则可以使用select.all_selected_options
得到一个列表。
如果页面中某些元素是ajax或js动态生成,并不是页面加载就存在的,那么我们就需要等待这些元素出现,官网示例如下:
1 | from selenium.webdriver.common.by import By |
上面的代码将在10秒内每隔0.5秒去寻找id为mydynamicelement的元素,by语法支持的方法也有很多,比如xpath,name,link_text等,具体请看文档。
这里多提一句,虽然最终在服务器上是没有图形界面的,但开发时可以使用webdriver.Firefox()来看代码逻辑等是否正确,这会启动一个真实的火狐浏览器进行操作,如果没问题再把引擎换成phantomjs。如果使用火狐的话,使用代理则变成:
1 | myProxy = "http://name:pswd@x.x.x.x:xxx" |
还有可能出现一种情况,就像我遇到的,每次修改文本框时都会重新加载页面某些元素,注意这里和上面说的“等待元素生成不同”,因为这个元素已经存在。所以有些时候需要使用time.sleep()函数等待,并且重新获取后再进行操作。
还有可能遇到的情况就是由于某些原因click事件不好使,或者某些隐藏元素只有在鼠标放在上面时才会显示出来,这时候可以采用下面的方法:
1 | menu = driver.find_element_by_css_selector(".nav") |
那么,如果得到某个元素后,需要得到某个属性怎么办呢?如何得到当前url以及页面源码?可以使用
1 | elem.get_attribute("value") # 取得属性值 |
最后再说一种“大杀器”:
1 | driver.execute_script("return navigator.userAgent") |
看名字也知道这是干嘛的,没错,就是执行自己写的js代码。比如上面写的就是获取当前浏览器的ua信息,至于这个怎么用就看具体情况了。