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,不然会失败。
driver.get_log('browser')
一样也会获得页面的 console.log 的输出,须要进行过滤。它的输出格式是
{"level": level, "message": message, "timestamp": timestamp}
,能够经过
filter(lambda x: 'url' in x, driver.get_log('browser'))
语句过滤掉。
摘自:http://www.jianshu.com/p/23a6f6fd6268
最近在作对网站的自动化测试,最开始使用 Python Requests 进行测试,测试经过,然而页面仍是会出现这样那样问题。一方面是由于测试用例还不够详细,另外一方面,Requests 是 url 层面或者说 api 层面的测试,并无彻底模拟用户在浏览器中的操做。好比,页面有些元素是 JS 动态生成的,Requests 是没法获得的;或者页面中的 img 或者 script 连接坏了,用 Requests 的话就须要去解析 html 了,这样若是网站对排版作一点点改动就要重写测试用例,很是费时费力。
通过一番搜索,了解到两个神器 Selenium 和 PhantomJS。关于这两个软件,就简单说一下,Selenium 是一个Web浏览器自动化测试框架,而 PhantomJS 是一个基于 Webkit 的无 UI 的浏览器,详细介绍请自行搜索。javascript
测试页面中哪些连接是坏的。html
Selenium 能够经过 PhantomJS 获取实际显示的页面(JS 动态生成的元素也能够获得),而且能够模拟用户对页面操做,可是上面提到的页面中的连接坏了或者页面的跳转,它也是没法感知的,这些动做其实在 PhantomJS 中均可以获得,可是若是没有作处理,在 Selenium 中是没法直接获得的。java
在 PhantomJS 中,能够经过许多的句柄来获取页面的动做。好比下面这个脚本能够记录整个页面访问的过程(netlog.js): git
"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
,能够获得以下相似的输出:github
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 语言,下同):web
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 的输出了。 api
首先是在 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')
读取的变量,把你想要的内容藏在这个变量里就行了。session
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 尚未测试过。app
做者:JerryKFC连接:http://www.jianshu.com/p/23a6f6fd6268來源:简书著做权归做者全部。商业转载请联系做者得到受权,非商业转载请注明出处。