在 Selenium 中让 PhantomJS 执行它的 API
from selenium import webdriver
driver = webdriver.PhantomJS()
script = "var page = this; page.onResourceError = function(res) {page.browserLog.push({'url': res.url, 'status': res.status});};"
driver.command_executor._commands['executePhantomScript'] = ('POST', '/session/$sessionId/phantom/execute')
driver.execute('executePhantomScript', {'script': script, 'args': []})
driver.get('http://www.baidu.com')
print(driver.get_log('browser'))
var page = this
,然后通过 page 变量来调用 API,否则会失败。2)
driver.get_log('browser')
同样也会得到页面的 console.log 的输出,需要进行过滤。它的输出格式是{"level": level, "message": message, "timestamp": timestamp}
,可以通过filter(lambda x: 'url' in x, driver.get_log('browser'))
语句过滤掉。3) 这个方法仅限于 PhantomJS,
摘自:http://www.jianshu.com/p/23a6f6fd6268
Selenium获取PhantomJS输出
0 背景
最近在做对网站的自动化测试,最开始使用 Python Requests 进行测试,测试通过,然而页面还是会出现这样那样问题。一方面是因为测试用例还不够详细,另一方面,Requests 是 url 层面或者说 api 层面的测试,并没有完全模拟用户在浏览器中的操作。比如,页面有些元素是 JS 动态生成的,Requests 是无法得到的;或者页面中的 img 或者 script 链接坏了,用 Requests 的话就需要去解析 html 了,这样如果网站对排版做一点点改动就要重写测试用例,非常费时费力。
经过一番搜索,了解到两个神器 Selenium 和 PhantomJS。关于这两个软件,就简单说一下,Selenium 是一个Web浏览器自动化测试框架,而 PhantomJS 是一个基于 Webkit 的无 UI 的浏览器,详细介绍请自行搜索。
1 目的
测试页面中哪些链接是坏的。
2 遇到的问题
Selenium 可以通过 PhantomJS 获取实际显示的页面(JS 动态生成的元素也可以得到),并且可以模拟用户对页面操作,但是上面提到的页面中的链接坏了或者页面的跳转,它也是无法感知的,这些动作其实在 PhantomJS 中都可以得到,但是如果没有做处理,在 Selenium 中是无法直接得到的。
3 解决
在 PhantomJS 中,可以通过许多的句柄来获取页面的动作。比如下面这个脚本可以记录整个页面访问的过程(netlog.js):
"use strict";
var page = require('webpage').create(),
system = require('system'),
address;
if (system.args.length === 1) {
console.log('Usage: netlog.js <some URL>');
phantom.exit(1);
} else {
address = system.args[1];
page.onResourceRequested = function (req) {
console.log('requested: ' + JSON.stringify(req, undefined, 4));
};
page.onResourceReceived = function (res) {
console.log('received: ' + JSON.stringify(res, undefined, 4));
};
page.open(address, function (status) {
if (status !== 'success') {
console.log('FAIL to load the address');
}
phantom.exit();
});
}
执行phantomjs netlog.js http://www.baidu.com
,可以得到如下类似的输出:
requested: {
"headers": [
{
"name": "Accept",
"value": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
},
{
"name": "User-Agent",
"value": "Mozilla/5.0 (Unknown; Linux x86_64) AppleWebKit/538.1 (KHTML, like Gecko) PhantomJS/2.1.1 Safari/538.1"
}
],
"id": 1,
"method": "GET",
"time": "2017-01-05T03:42:14.125Z",
"url": "http://www.baidu.com/"
}
received: {
"body": "",
"bodySize": 215,
"contentType": "text/html",
"headers": [
{
"name": "Date",
"value": "Thu, 05 Jan 2017 03:42:14 GMT"
},
{
"name": "Content-Type",
"value": "text/html"
},
{
"name": "Content-Length",
"value": "215"
},
...
Selenium 正常调用 PhantomJS 的方法如下(Python 语言,下同):
from selenium import webdriver
driver = webdriver.PhantomJS()
driver.get('http://www.baidu.com')
print(driver.get_log('browser'))
其中最后一条语句可以得到页面的 console.log 的输出,同时会生成一个 ghostdriver.log 的文件,其中是 PhantomJS 的日志。
接下来就是如何在 Selenium 中获取 PhantomJS 的输出了。
首先是在 Selenium 中让 PhantomJS 执行它的 API 的 Hack(参考):
driver = webdriver.PhantomJS()
script = "this.onResourceError = function(res) {console.log(JSON.stringify({'url': res.url, 'status': res.status}));};"
driver.command_executor._commands['executePhantomScript'] = ('POST', '/session/$sessionId/phantom/execute')
driver.execute('executePhantomScript', {'script': script, 'args': []})
但是这样通过driver.get_log('browser')
是得不到想要的内容的,因为虽然和页面 JS 的 console.log 是同样的名字,然而 PhantomJS API 的 console.log 的输出是在刚才提到的 ghostdriver.log 文件中,当然你也可以每次就读取该文件来获取内容(可以通过 webdriver 的 service_log_path 参数来设置文件名)。笔者觉得这样不够优雅,于是继续……
通过阅读 PhantomJS 的源码,终于在 session.js 找到了一个隐藏的变量 browserLog 来实现这个功能,这个变量其实就是driver.get_log('browser')
读取的变量,把你想要的内容藏在这个变量里就好了。
from selenium import webdriver
driver = webdriver.PhantomJS()
script = "var page = this; page.onResourceError = function(res) {page.browserLog.push({'url': res.url, 'status': res.status});};"
driver.command_executor._commands['executePhantomScript'] = ('POST', '/session/$sessionId/phantom/execute')
driver.execute('executePhantomScript', {'script': script, 'args': []})
driver.get('http://www.baidu.com')
print(driver.get_log('browser'))
需要注意的是,1) PhantomJS 脚本中必须执行语句var page = this
,然后通过 page 变量来调用 API,否则会失败。
2) driver.get_log('browser')
同样也会得到页面的 console.log 的输出,需要进行过滤。它的输出格式是{"level": level, "message": message, "timestamp": timestamp}
,可以通过filter(lambda x: 'url' in x, driver.get_log('browser'))
语句过滤掉。
3) 这个方法仅限于 PhantomJS,其他的 WebDriver 还没有测试过。
作者:JerryKFC
链接:http://www.jianshu.com/p/23a6f6fd6268
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
在 Selenium 中让 PhantomJS 执行它的 API的更多相关文章
- Python selenium中注入并执行Javascript语句
众所周知,Python通常结合selenium模块来完成一些web的自动化测试以及RPA(Robotic Process Automation)工作.事实上,Selenium还可以支持插入js语句.执 ...
- PhantomJS在Selenium中被标记为过时的应对措施
今天使用PhantomJS时,Selenium提示PhantomJS被标记不赞成,我就蒙了.PhantomJS可是Headless浏览器中相当知名的一款,标记为过时,代表着将在未来版本摒弃掉这个支持. ...
- selenium + firefox/chrome/phantomjs登陆之模拟点击
登陆之模拟点击 工具:python/java + selenium + firefox/chrome/phantomjs (1)windows开发环境搭建 默认已经安装好了firefox 安装pip ...
- 爬虫之图片懒加载技术、selenium工具与PhantomJS无头浏览器
图片懒加载技术 selenium爬虫简单使用 2.1 selenium简介 2.2 selenium安装 2.3 selenium简单使用 2.3.1 selenium使用案例 2.3.2 selen ...
- Selenium中的几种等待方式,需特别注意implicitlyWait的用法
摘:http://blog.csdn.net/pf20050904/article/details/20052485 最近在项目过程中使用selenium 判断元素是否存在的时候 遇到一个很坑爹的问题 ...
- 转:Selenium中的几种等待方式,需特别注意implicitlyWait的用法
最近在项目过程中使用selenium 判断元素是否存在的时候 遇到一个很坑爹的问题, 用以下方法执行的时候每次都会等待很长一段时间,原因是因为对selenium实现方法了解不足导致一直找不到解决方法. ...
- Selenium中三种等待的使用方式---规避网络延迟、代码不稳定问题
在UI自动化测试中,必然会遇到环境不稳定,网络慢的情况,这时如果你不做任何处理的话,代码会由于没有找到元素,而报错.这时我们就要用到wait(等待),而在Selenium中,我们可以用到一共三种等待, ...
- 第三百三十七节,web爬虫讲解2—PhantomJS虚拟浏览器+selenium模块操作PhantomJS
第三百三十七节,web爬虫讲解2—PhantomJS虚拟浏览器+selenium模块操作PhantomJS PhantomJS虚拟浏览器 phantomjs 是一个基于js的webkit内核无头浏览器 ...
- selenium中的三种等待方式(显示等待WebDriverWait()、隐式等待implicitly()、强制等待sleep())---基于python
我们在实际使用selenium或者appium时,等待下个等待定位的元素出现,特别是web端加载的过程,都需要用到等待,而等待方式的设置是保证脚本稳定有效运行的一个非常重要的手段,在selenium中 ...
随机推荐
- drools6
<dependency> <groupId>org.drools</groupId> <artifactId>drools-core</artif ...
- g2o初始化一些
今天看了一下智能指针的东西,发现更简单的思路: 就是Block和solver构造时,需要传递unique_ptr,那我们将普通指针转换成unique_ptr不就可以了么: // 初始化g2o //第一 ...
- #ifndef 的用法介绍
ifndef是 if not define 的缩写,一种宏定义.它是预处理功能中三种(宏定义,文件包含和条件编译)中的第三种--条件编译. 其使用方式是: #define X ... #endif / ...
- 17.2.10 NOIP模拟赛 聪哥的工资
聪哥的工资 (money/money.in/money.out) 时限1000ms 内存256MB 题目描述 lwher: 了体验劳苦大众的生活,聪哥在暑假参加了打零工的活动,这个活动分为n个工作日, ...
- C#后台无刷新页面弹出alert方法
原文发布时间为:2009-05-17 -- 来源于本人的百度文章 [由搬家工具导入] 无刷新弹出警告: ScriptManager.RegisterStartupScript(this. ...
- vmware tools安装过程
每次通过vmware安装Ubuntu的时候,总是会多多少少出点问题.好容易披荆斩棘把镜像安好了,然而屏幕却只有小小一个,不能显示大屏,我就知道肯定是缺少了vmware tools.于是点击左上方菜单中 ...
- javascript 之 className属性
Javascript 可以通过className 属性灵活的更改一个标签元素的CSS 类选择器来实现样式的变化. 1.用className 属性修改节点的css类别 代码如下: <html> ...
- 【linux高级程序设计】(第八章)进程管理与程序开发 5
守候进程 启动方式: 在系统启动时由/etc/rd.d目录下的启动脚本启动 利用inetd超级服务器启动 有cron命令定时启动,以及在终端用nohup命令启动 守护进程编程要点 (1)屏蔽有关控制终 ...
- 阻止关闭窗口,FormCloseQuery
procedure TfrmTopJdsMain.FormCloseQuery(Sender: TObject; var CanClose: Boolean); begin ) = mrNo then ...
- 前端优化之Combo Handler
Combo Handler来合并CSS/JS文件 背景 Combo Handler是Yahoo!开发的一个Apache模块,它实现了开发人员简单方便地通过URL来合并JavaScript和CSS文件, ...