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來源:簡書著做權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。